Changeset fa3ed5b in mainline


Ignore:
Timestamp:
2025-01-16T17:27:32Z (28 hours ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Children:
df721df
Parents:
96368f56
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-01-16 14:30:47)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2025-01-16 17:27:32)
Message:

Bulk clear capabilities when task terminates or is destroyed

Location:
kernel/generic
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/cap/cap.h

    r96368f56 rfa3ed5b  
    130130extern errno_t caps_task_alloc(struct task *);
    131131extern void caps_task_free(struct task *);
    132 extern void caps_task_init(struct task *);
     132extern void caps_task_clear(struct task *task);
     133extern errno_t caps_task_init(struct task *);
    133134extern bool caps_apply_to_kobject_type(struct task *, kobject_type_t,
    134135    bool (*)(cap_t *, void *), void *);
  • kernel/generic/src/cap/cap.c

    r96368f56 rfa3ed5b  
    9393
    9494#define CAPS_START      ((intptr_t) CAP_NIL + 1)
    95 #define CAPS_SIZE       (INT_MAX - (int) CAPS_START)
    96 #define CAPS_LAST       (CAPS_SIZE - 1)
     95#define CAPS_LAST       ((intptr_t) INT_MAX - 1)
     96#define CAPS_SIZE       (CAPS_LAST - CAPS_START + 1)
    9797
    9898static slab_cache_t *cap_cache;
     
    125125}
    126126
     127static void caps_remove_callback(ht_link_t *item)
     128{
     129        cap_t *cap = hash_table_get_inst(item, cap_t, caps_link);
     130
     131        if (cap->kobject) {
     132                kobject_t *kobj = cap->kobject;
     133
     134                mutex_lock(&kobj->caps_list_lock);
     135                cap->kobject = NULL;
     136                list_remove(&cap->kobj_link);
     137                mutex_unlock(&kobj->caps_list_lock);
     138
     139                kobject_put(kobj);
     140        }
     141
     142        list_remove(&cap->type_link);
     143
     144        slab_free(cap_cache, cap);
     145}
     146
    127147static const hash_table_ops_t caps_ops = {
    128148        .hash = caps_hash,
    129149        .key_hash = caps_key_hash,
    130         .key_equal = caps_key_equal
     150        .key_equal = caps_key_equal,
     151        .remove_callback = caps_remove_callback,
    131152};
    132153
     
    148169        if (!task->cap_info)
    149170                return ENOMEM;
     171
     172        if (!hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops)) {
     173                free(task->cap_info);
     174                return ENOMEM;
     175        }
     176
     177        mutex_initialize(&task->cap_info->lock, MUTEX_RECURSIVE);
     178
     179        task->cap_info->handles = NULL;
     180
     181        for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++)
     182                list_initialize(&task->cap_info->type_list[t]);
     183
     184        return EOK;
     185}
     186
     187/** Initialize the capability info structure
     188 *
     189 * @param task  Task for which to initialize the info structure.
     190 */
     191errno_t caps_task_init(task_t *task)
     192{
     193        assert(task->cap_info);
     194        assert(!task->cap_info->handles);
     195
    150196        task->cap_info->handles = ra_arena_create();
    151197        if (!task->cap_info->handles)
    152                 goto error_handles;
    153         if (!ra_span_add(task->cap_info->handles, CAPS_START, CAPS_SIZE))
    154                 goto error_span;
    155         if (!hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops))
    156                 goto error_span;
     198                return ENOMEM;
     199
     200        if (!ra_span_add(task->cap_info->handles, CAPS_START, CAPS_SIZE)) {
     201                ra_arena_destroy(task->cap_info->handles);
     202                return ENOMEM;
     203        }
     204
    157205        return EOK;
    158 
    159 error_span:
    160         ra_arena_destroy(task->cap_info->handles);
    161 error_handles:
    162         free(task->cap_info);
    163         return ENOMEM;
    164 }
    165 
    166 /** Initialize the capability info structure
    167  *
    168  * @param task  Task for which to initialize the info structure.
    169  */
    170 void caps_task_init(task_t *task)
    171 {
    172         mutex_initialize(&task->cap_info->lock, MUTEX_RECURSIVE);
     206}
     207
     208void caps_task_clear(task_t *task)
     209{
     210        mutex_lock(&task->cap_info->lock);
     211
     212        hash_table_clear(&task->cap_info->caps);
     213
     214        if (task->cap_info->handles) {
     215                ra_arena_destroy(task->cap_info->handles);
     216                task->cap_info->handles = NULL;
     217        }
    173218
    174219        for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++)
    175220                list_initialize(&task->cap_info->type_list[t]);
     221
     222        mutex_unlock(&task->cap_info->lock);
    176223}
    177224
     
    183230{
    184231        hash_table_destroy(&task->cap_info->caps);
    185         ra_arena_destroy(task->cap_info->handles);
     232
     233        if (task->cap_info->handles)
     234                ra_arena_destroy(task->cap_info->handles);
     235
    186236        free(task->cap_info);
    187237}
     
    300350cap_publish(task_t *task, cap_handle_t handle, kobject_t *kobj)
    301351{
     352        mutex_lock(&task->cap_info->lock);
    302353        mutex_lock(&kobj->caps_list_lock);
    303         mutex_lock(&task->cap_info->lock);
    304354        cap_t *cap = cap_get(task, handle, CAP_STATE_ALLOCATED);
    305355        assert(cap);
     
    309359        list_append(&cap->kobj_link, &kobj->caps_list);
    310360        list_append(&cap->type_link, &task->cap_info->type_list[kobj->type]);
    311         mutex_unlock(&task->cap_info->lock);
    312361        mutex_unlock(&kobj->caps_list_lock);
     362        mutex_unlock(&task->cap_info->lock);
    313363}
    314364
     
    340390        kobject_t *kobj = NULL;
    341391
    342 restart:
    343392        mutex_lock(&task->cap_info->lock);
    344393        cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED);
     
    347396                        /* Hand over cap's reference to kobj */
    348397                        kobj = cap->kobject;
    349                         if (mutex_trylock(&kobj->caps_list_lock) != EOK) {
    350                                 mutex_unlock(&task->cap_info->lock);
    351                                 kobj = NULL;
    352                                 goto restart;
    353                         }
     398
     399                        mutex_lock(&kobj->caps_list_lock);
    354400                        cap_unpublish_unsafe(cap);
    355401                        mutex_unlock(&kobj->caps_list_lock);
     
    376422{
    377423        mutex_lock(&kobj->caps_list_lock);
    378         list_foreach_safe(kobj->caps_list, cur, hlp) {
    379                 cap_t *cap = list_get_instance(cur, cap_t, kobj_link);
    380                 mutex_lock(&cap->task->cap_info->lock);
     424
     425        while (!list_empty(&kobj->caps_list)) {
     426                cap_t *cap = list_get_instance(list_first(&kobj->caps_list), cap_t, kobj_link);
     427
     428                /* We're trying to acquire the two locks in reverse order. */
     429                if (mutex_trylock(&cap->task->cap_info->lock) != EOK) {
     430                        mutex_unlock(&kobj->caps_list_lock);
     431                        mutex_lock(&kobj->caps_list_lock);
     432                        continue;
     433                }
     434
    381435                cap_unpublish_unsafe(cap);
    382436                /* Drop the reference for the unpublished capability */
    383437                kobject_put(kobj);
     438
    384439                mutex_unlock(&cap->task->cap_info->lock);
    385440        }
     441
    386442        mutex_unlock(&kobj->caps_list_lock);
    387443}
     
    404460        hash_table_remove_item(&task->cap_info->caps, &cap->caps_link);
    405461        ra_free(task->cap_info->handles, cap_handle_raw(handle), 1);
    406         slab_free(cap_cache, cap);
    407462        mutex_unlock(&task->cap_info->lock);
    408463}
  • kernel/generic/src/proc/task.c

    r96368f56 rfa3ed5b  
    201201                return NULL;
    202202
     203        if (caps_task_init(task) != EOK) {
     204                slab_free(task_cache, task);
     205                return NULL;
     206        }
     207
    203208        refcount_init(&task->refcount);
    204209
     
    212217        task->ucycles = 0;
    213218        task->kcycles = 0;
    214 
    215         caps_task_init(task);
    216219
    217220        task->ipc_info.call_sent = 0;
     
    287290         */
    288291        as_release(task->as);
     292
     293        caps_task_clear(task);
    289294
    290295        slab_free(task_cache, task);
  • kernel/generic/src/proc/thread.c

    r96368f56 rfa3ed5b  
    445445                        ipc_cleanup();
    446446                        sys_waitq_task_cleanup();
     447                        caps_task_clear(TASK);
    447448                        LOG("Cleanup of task %" PRIu64 " completed.", TASK->taskid);
    448449                }
Note: See TracChangeset for help on using the changeset viewer.