task_delete(): Do not permit user applications to delete kernel threads.

This commit is contained in:
Gregory Nutt 2017-10-16 09:07:17 -06:00
parent c8eb0a4880
commit b1a41b7620
3 changed files with 63 additions and 18 deletions

1
TODO
View File

@ -789,7 +789,6 @@ o Kernel/Protected Build
Description: Certain interfaces, such as sched_setparam(), Description: Certain interfaces, such as sched_setparam(),
sched_setscheduler(), etc. can be used by user mode tasks to sched_setscheduler(), etc. can be used by user mode tasks to
modify the behavior of priviledged kernel threads. modify the behavior of priviledged kernel threads.
task_delete() could even be used to kill a kernel thread.
For a truly secure system. Privileges need to be checked in For a truly secure system. Privileges need to be checked in
every interface that permits one thread to modify the every interface that permits one thread to modify the
properties of another thread. properties of another thread.

View File

@ -2,7 +2,7 @@
* include/nuttx/kthread.h * include/nuttx/kthread.h
* Non-standard, NuttX-specific kernel thread-related declarations. * Non-standard, NuttX-specific kernel thread-related declarations.
* *
* Copyright (C) 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2013, 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -83,6 +83,29 @@ extern "C"
int kernel_thread(FAR const char *name, int priority, int stack_size, int kernel_thread(FAR const char *name, int priority, int stack_size,
main_t entry, FAR char * const argv[]); main_t entry, FAR char * const argv[]);
/****************************************************************************
* Name: kthread_delete
*
* Description:
* This function will terminate a kernel thread. At present, this
* function is equivalent to task_delete.c; the following definition
* simply reserves the name in the name space.
*
* Refer to comments with task_delete() for a more detailed description of
* the operation of this function.
*
* Input Parameters:
* pid - The task ID of the task to delete. A pid of zero
* signifies the calling task.
*
* Returned Value:
* OK on success; or ERROR on failure with the errno variable set
* appropriately.
*
****************************************************************************/
#define kthread_delete(p) task_delete(p)
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -1,7 +1,8 @@
/**************************************************************************** /****************************************************************************
* sched/task/task_delete.c * sched/task/task_delete.c
* *
* Copyright (C) 2007-2009, 2011-2013, 2016 Gregory Nutt. All rights reserved. * Copyright (C) 2007-2009, 2011-2013, 2016-2017 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -55,25 +56,26 @@
* Name: task_delete * Name: task_delete
* *
* Description: * Description:
* This function causes a specified task to cease to exist. Its stack and * This function causes a specified task to cease to exist. Its stack and
* TCB will be deallocated. This function is the companion to task_create(). * TCB will be deallocated. This function is the companion to
* This is the version of the function exposed to the user; it is simply * task_create(). This is the version of the function exposed to the
* a wrapper around the internal, task_terminate function. * user; it is simply a wrapper around the internal, task_terminate
* function.
* *
* The logic in this function only deletes non-running tasks. If the 'pid' * The logic in this function only deletes non-running tasks. If the
* parameter refers to to the currently runing task, then processing is * 'pid' parameter refers to to the currently runing task, then processing
* redirected to exit(). This can only happen if a task calls task_delete() * is redirected to exit(). This can only happen if a task calls
* in order to delete itself. * task_delete()in order to delete itself.
* *
* This function obeys the semantics of pthread cancellation: task * This function obeys the semantics of pthread cancellation: task
* deletion is deferred if cancellation is disabled or if deferred * deletion is deferred if cancellation is disabled or if deferred
* cancellation is supported (with cancellation points enabled). * cancellation is supported (with cancellation points enabled).
* *
* Inputs: * Input Parameters:
* pid - The task ID of the task to delete. A pid of zero * pid - The task ID of the task to delete. A pid of zero
* signifies the calling task. * signifies the calling task.
* *
* Return Value: * Returned Value:
* OK on success; or ERROR on failure with the errno variable set * OK on success; or ERROR on failure with the errno variable set
* appropriately. * appropriately.
* *
@ -83,6 +85,7 @@ int task_delete(pid_t pid)
{ {
FAR struct tcb_s *dtcb; FAR struct tcb_s *dtcb;
FAR struct tcb_s *rtcb; FAR struct tcb_s *rtcb;
int errcode;
int ret; int ret;
/* Check if the task to delete is the calling task: PID=0 means to delete /* Check if the task to delete is the calling task: PID=0 means to delete
@ -105,14 +108,30 @@ int task_delete(pid_t pid)
* has probably already exited. * has probably already exited.
*/ */
set_errno(ESRCH); errcode = ESRCH;
return ERROR; goto errout;
} }
/* Only tasks and kernel threads should use this interface */ /* Only tasks and kernel threads can be deleted with this interface
* (The semantics of the call should be sufficient to prohibit this).
*/
DEBUGASSERT((dtcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD); DEBUGASSERT((dtcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD);
/* Non-privileged tasks and pthreads may not delete privileged kernel
* threads.
*
* REVISIT: We will need to look at this again in the future if/when
* permissions are supported and a user task might also be priveleged.
*/
if (((rtcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL) &&
((dtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL))
{
errcode = EACCES;
goto errout;
}
/* Check to see if this task has the non-cancelable bit set in its /* Check to see if this task has the non-cancelable bit set in its
* flags. Suppress context changes for a bit so that the flags are stable. * flags. Suppress context changes for a bit so that the flags are stable.
* (the flags should not change in interrupt handling). * (the flags should not change in interrupt handling).
@ -183,9 +202,13 @@ int task_delete(pid_t pid)
ret = task_terminate(pid, false); ret = task_terminate(pid, false);
if (ret < 0) if (ret < 0)
{ {
set_errno(-ret); errcode = -ret;
return ERROR; goto errout;
} }
return OK; return OK;
errout:
set_errno(errcode);
return ERROR;
} }