From 8d968ab4939f70a712cbc009a9135e04ca716d32 Mon Sep 17 00:00:00 2001 From: HeatCrab Date: Tue, 3 Feb 2026 19:24:42 +0800 Subject: [PATCH] Add U-mode task isolation and fix self-termination U-mode tasks could previously control other tasks and had no way to properly terminate themselves. This adds permission checks to restrict task control syscalls to self-only operations and enables safe self-termination through the existing zombie task mechanism. --- kernel/syscall.c | 19 ++++++++++++------- kernel/task.c | 17 +++++++++++++++-- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/kernel/syscall.c b/kernel/syscall.c index 3313774..c47f673 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -266,8 +266,10 @@ int sys_task_spawn(void *task, int stack_size) static int _tcancel(int id) { - if (unlikely(id <= 0)) + if (unlikely(id <= 0 || id > (int) UINT16_MAX)) return -EINVAL; + if ((uint16_t) id != mo_task_id()) + return -EPERM; return mo_task_cancel(id); } @@ -304,8 +306,10 @@ int sys_tdelay(int ticks) static int _tsuspend(int id) { - if (unlikely(id <= 0)) + if (unlikely(id <= 0 || id > (int) UINT16_MAX)) return -EINVAL; + if ((uint16_t) id != mo_task_id()) + return -EPERM; return mo_task_suspend(id); } @@ -317,10 +321,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) @@ -330,8 +333,10 @@ int sys_tresume(int id) static int _tpriority(int id, int priority) { - if (unlikely(id <= 0)) + if (unlikely(id <= 0 || id > (int) UINT16_MAX)) return -EINVAL; + if ((uint16_t) id != mo_task_id()) + return -EPERM; return mo_task_priority(id, priority); } diff --git a/kernel/task.c b/kernel/task.c index 286e83e..b269843 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -395,7 +395,7 @@ static void task_cleanup_zombies(void) list_node_t *next = list_next(node); tcb_t *tcb = node->data; - if (tcb && tcb->state == TASK_ZOMBIE) { + if (tcb && tcb->state == TASK_ZOMBIE && node != kcb->task_current) { /* Remove from task list */ list_remove(kcb->tasks, node); kcb->task_count--; @@ -992,9 +992,22 @@ 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; + CRITICAL_ENTER(); + self->state = TASK_ZOMBIE; + CRITICAL_LEAVE(); + _yield(); + while (1) + ; + } + CRITICAL_ENTER(); list_node_t *node = find_task_node_by_id(id); if (!node) {