Changeset 07d4271 in mainline for kernel/generic/src/sysinfo/stats.c


Ignore:
Timestamp:
2024-01-25T16:22:55Z (17 months ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
master
Children:
f8b69a1e
Parents:
1a1e124
git-author:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-01-25 15:56:31)
git-committer:
Jiří Zárevúcky <zarevucky.jiri@…> (2024-01-25 16:22:55)
Message:

Fix some unsound task reference manipulation and locking

In some operations that take task ID as an argument,
there's a possibility of the task being destroyed mid-operation
and a subsequent use-after-free situation.
As a general solution, task_find_by_id() is reimplemented to
check for this situation and always return a valid strong reference.
The callers then only need to handle the reference itself, and
don't need to concern themselves with tasks_lock.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/sysinfo/stats.c

    r1a1e124 r07d4271  
    221221        stats_task->virtmem = get_task_virtmem(task->as);
    222222        stats_task->resmem = get_task_resmem(task->as);
    223         stats_task->threads = atomic_load(&task->refcount);
     223        stats_task->threads = atomic_load(&task->lifecount);
    224224        task_get_accounting(task, &(stats_task->ucycles),
    225225            &(stats_task->kcycles));
     
    511511{
    512512        /* Initially no return value */
    513         sysinfo_return_t ret;
    514         ret.tag = SYSINFO_VAL_UNDEFINED;
     513        sysinfo_return_t ret = {
     514                .tag = SYSINFO_VAL_UNDEFINED,
     515        };
    515516
    516517        /* Parse the task ID */
     
    519520                return ret;
    520521
    521         /* Messing with task structures, avoid deadlock */
    522         irq_spinlock_lock(&tasks_lock, true);
    523 
    524522        task_t *task = task_find_by_id(task_id);
    525         if (task == NULL) {
    526                 /* No task with this ID */
    527                 irq_spinlock_unlock(&tasks_lock, true);
     523        if (!task)
    528524                return ret;
    529         }
    530525
    531526        if (dry_run) {
     
    533528                ret.data.data = NULL;
    534529                ret.data.size = sizeof(stats_task_t);
    535 
    536                 irq_spinlock_unlock(&tasks_lock, true);
    537530        } else {
    538531                /* Allocate stats_task_t structure */
    539                 stats_task_t *stats_task =
    540                     (stats_task_t *) malloc(sizeof(stats_task_t));
    541                 if (stats_task == NULL) {
    542                         irq_spinlock_unlock(&tasks_lock, true);
    543                         return ret;
     532                stats_task_t *stats_task = malloc(sizeof(stats_task_t));
     533
     534                if (stats_task != NULL) {
     535                        /* Correct return value */
     536                        ret.tag = SYSINFO_VAL_FUNCTION_DATA;
     537                        ret.data.data = stats_task;
     538                        ret.data.size = sizeof(stats_task_t);
     539
     540                        irq_spinlock_lock(&task->lock, true);
     541                        produce_stats_task(task, stats_task);
     542                        irq_spinlock_unlock(&task->lock, true);
    544543                }
    545 
    546                 /* Correct return value */
    547                 ret.tag = SYSINFO_VAL_FUNCTION_DATA;
    548                 ret.data.data = (void *) stats_task;
    549                 ret.data.size = sizeof(stats_task_t);
    550 
    551                 /* Hand-over-hand locking */
    552                 irq_spinlock_exchange(&tasks_lock, &task->lock);
    553 
    554                 produce_stats_task(task, stats_task);
    555 
    556                 irq_spinlock_unlock(&task->lock, true);
    557         }
    558 
     544        }
     545
     546        task_release(task);
    559547        return ret;
    560548}
Note: See TracChangeset for help on using the changeset viewer.