Skip to content

Commit 8d968ab

Browse files
committed
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.
1 parent 37f9906 commit 8d968ab

2 files changed

Lines changed: 27 additions & 9 deletions

File tree

kernel/syscall.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,10 @@ int sys_task_spawn(void *task, int stack_size)
266266

267267
static int _tcancel(int id)
268268
{
269-
if (unlikely(id <= 0))
269+
if (unlikely(id <= 0 || id > (int) UINT16_MAX))
270270
return -EINVAL;
271+
if ((uint16_t) id != mo_task_id())
272+
return -EPERM;
271273

272274
return mo_task_cancel(id);
273275
}
@@ -304,8 +306,10 @@ int sys_tdelay(int ticks)
304306

305307
static int _tsuspend(int id)
306308
{
307-
if (unlikely(id <= 0))
309+
if (unlikely(id <= 0 || id > (int) UINT16_MAX))
308310
return -EINVAL;
311+
if ((uint16_t) id != mo_task_id())
312+
return -EPERM;
309313

310314
return mo_task_suspend(id);
311315
}
@@ -317,10 +321,9 @@ int sys_tsuspend(int id)
317321

318322
static int _tresume(int id)
319323
{
320-
if (unlikely(id <= 0))
321-
return -EINVAL;
322-
323-
return mo_task_resume(id);
324+
(void) id;
325+
/* U-mode cannot resume any task; suspended task cannot call syscall */
326+
return -EPERM;
324327
}
325328

326329
int sys_tresume(int id)
@@ -330,8 +333,10 @@ int sys_tresume(int id)
330333

331334
static int _tpriority(int id, int priority)
332335
{
333-
if (unlikely(id <= 0))
336+
if (unlikely(id <= 0 || id > (int) UINT16_MAX))
334337
return -EINVAL;
338+
if ((uint16_t) id != mo_task_id())
339+
return -EPERM;
335340

336341
return mo_task_priority(id, priority);
337342
}

kernel/task.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ static void task_cleanup_zombies(void)
395395
list_node_t *next = list_next(node);
396396
tcb_t *tcb = node->data;
397397

398-
if (tcb && tcb->state == TASK_ZOMBIE) {
398+
if (tcb && tcb->state == TASK_ZOMBIE && node != kcb->task_current) {
399399
/* Remove from task list */
400400
list_remove(kcb->tasks, node);
401401
kcb->task_count--;
@@ -992,9 +992,22 @@ int32_t mo_task_spawn_user(void *task_entry, uint16_t stack_size)
992992

993993
int32_t mo_task_cancel(uint16_t id)
994994
{
995-
if (id == 0 || id == mo_task_id())
995+
if (id == 0)
996996
return ERR_TASK_CANT_REMOVE;
997997

998+
/* Self-termination marks the task as zombie and yields to the scheduler.
999+
* The dispatcher will reclaim resources after context switch completes.
1000+
*/
1001+
if (id == mo_task_id()) {
1002+
tcb_t *self = kcb->task_current->data;
1003+
CRITICAL_ENTER();
1004+
self->state = TASK_ZOMBIE;
1005+
CRITICAL_LEAVE();
1006+
_yield();
1007+
while (1)
1008+
;
1009+
}
1010+
9981011
CRITICAL_ENTER();
9991012
list_node_t *node = find_task_node_by_id(id);
10001013
if (!node) {

0 commit comments

Comments
 (0)