Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,8 @@ int sys_task_spawn(void *task, int stack_size)

static int _tcancel(int id)
{
if (unlikely(id <= 0))
return -EINVAL;
if (id <= 0 || (uint16_t) id != mo_task_id())
return -EPERM;

return mo_task_cancel(id);
}
Expand Down Expand Up @@ -316,8 +316,8 @@ int sys_tdelay(int ticks)

static int _tsuspend(int id)
{
if (unlikely(id <= 0))
return -EINVAL;
if (id <= 0 || (uint16_t) id != mo_task_id())
return -EPERM;

return mo_task_suspend(id);
}
Expand All @@ -329,10 +329,9 @@ int sys_tsuspend(int id)

static int _tresume(int id)
{
if (unlikely(id <= 0))
return -EINVAL;

return mo_task_resume(id);
(void) id;
/* U-mode cannot resume any task; suspended task cannot call syscall */
return -EPERM;
}

int sys_tresume(int id)
Expand All @@ -342,8 +341,8 @@ int sys_tresume(int id)

static int _tpriority(int id, int priority)
{
if (unlikely(id <= 0))
return -EINVAL;
if (id <= 0 || (uint16_t) id != mo_task_id())
return -EPERM;

return mo_task_priority(id, priority);
}
Expand Down
13 changes: 12 additions & 1 deletion kernel/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -992,9 +992,20 @@ int32_t mo_task_spawn_user(void *task_entry, uint16_t stack_size)

int32_t mo_task_cancel(uint16_t id)
{
if (id == 0 || id == mo_task_id())
if (id == 0)
return ERR_TASK_CANT_REMOVE;

/* Self-termination marks the task as zombie and yields to the scheduler.
* The dispatcher will reclaim resources after context switch completes.
*/
if (id == mo_task_id()) {
tcb_t *self = kcb->task_current->data;
self->state = TASK_ZOMBIE;
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Marking the current task as TASK_ZOMBIE before _yield() lets dispatch() free the running task in task_cleanup_zombies(), then dereference kcb->task_current->data during context save/scheduling. This introduces a use-after-free on self-termination. Defer freeing the current task until after the context switch or skip cleanup of the current task.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At kernel/task.c, line 1003:

<comment>Marking the current task as TASK_ZOMBIE before _yield() lets dispatch() free the running task in task_cleanup_zombies(), then dereference kcb->task_current->data during context save/scheduling. This introduces a use-after-free on self-termination. Defer freeing the current task until after the context switch or skip cleanup of the current task.</comment>

<file context>
@@ -992,9 +992,20 @@ int32_t mo_task_spawn_user(void *task_entry, uint16_t stack_size)
+     */
+    if (id == mo_task_id()) {
+        tcb_t *self = kcb->task_current->data;
+        self->state = TASK_ZOMBIE;
+        _yield();
+        while (1)
</file context>
Fix with Cubic

_yield();
while (1)
;
}

CRITICAL_ENTER();
list_node_t *node = find_task_node_by_id(id);
if (!node) {
Expand Down
Loading