diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 09916b833d6..ddb650e2d9f 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -456,6 +457,7 @@ struct task_group_s pid_t tg_pid; /* The ID of the task within the group */ pid_t tg_ppid; /* This is the ID of the parent thread */ uint8_t tg_flags; /* See GROUP_FLAG_* definitions */ + uint8_t tg_caps; /* See PR_CAP_* definitions */ /* User identity (POSIX real, effective, and saved-set IDs) ***************/ @@ -924,6 +926,12 @@ static inline_function bool nxsched_has_gid(FAR struct tcb_s *tcb, FAR struct tcb_s *nxsched_self(void); +#ifdef CONFIG_SCHED_CAPABILITIES +# define nxsched_capable(c) ((nxsched_self()->group->tg_caps & (c)) == (c)) +#else +# define nxsched_capable(c) true +#endif + /**************************************************************************** * Name: nxsched_foreach * diff --git a/include/sys/prctl.h b/include/sys/prctl.h index aea419244f2..9315266b357 100644 --- a/include/sys/prctl.h +++ b/include/sys/prctl.h @@ -78,6 +78,13 @@ #define PR_SET_DUMPABLE 5 #define PR_GET_DUMPABLE 6 +#define PR_CAPS_DROP 7 +#define PR_CAPS_GET 8 + +#define PR_CAP_RAWIO (1 << 0) +#define PR_CAP_SPAWN (1 << 1) +#define PR_CAP_ADMIN (1 << 2) +#define PR_CAP_ALL (PR_CAP_RAWIO | PR_CAP_SPAWN | PR_CAP_ADMIN) /**************************************************************************** * Public Type Definitions diff --git a/sched/Kconfig b/sched/Kconfig index ed0e8c512f4..b20c4be8584 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -817,6 +817,17 @@ config SCHED_NGROUPS endif # SCHED_USER_IDENTITY +config SCHED_CAPABILITIES + bool "Process capabilities" + default !DEFAULT_SMALL + ---help--- + Task groups hold PR_CAP_RAWIO, PR_CAP_SPAWN and PR_CAP_ADMIN, + inherit them from their creator and can drop them with + prctl(PR_CAPS_DROP). Raw storage, mount, spawn, reset and + power-off then need the matching capability. Without this + option every check passes and prctl() refuses PR_CAPS_DROP and + PR_CAPS_GET. + config SCHED_THREAD_LOCAL bool "Support __thread/thread_local keyword" default n diff --git a/sched/group/group_create.c b/sched/group/group_create.c index 71e288c7bd8..5febd80e11b 100644 --- a/sched/group/group_create.c +++ b/sched/group/group_create.c @@ -196,6 +196,7 @@ int group_allocate(FAR struct tcb_s *tcb, uint8_t ttype) { group = &g_kthread_group; tcb->group = group; + group->tg_caps = PR_CAP_ALL; if (group->tg_info) { return OK; @@ -250,6 +251,9 @@ int group_allocate(FAR struct tcb_s *tcb, uint8_t ttype) goto errout_with_group; } + group->tg_caps = this_task()->group != NULL ? + this_task()->group->tg_caps : PR_CAP_ALL; + /* Initialize file descriptors for the TCB */ fdlist_init(&group->tg_fdlist); diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index dd27cdf9f73..7953744a871 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -476,6 +476,7 @@ static void idle_group_initialize(void) group_initialize(tcb); tcb->group->tg_flags = GROUP_FLAG_NOCLDWAIT | GROUP_FLAG_PRIVILEGED; + tcb->group->tg_caps = PR_CAP_ALL; } } diff --git a/sched/task/task_prctl.c b/sched/task/task_prctl.c index b065eeae833..988613b11f0 100644 --- a/sched/task/task_prctl.c +++ b/sched/task/task_prctl.c @@ -187,20 +187,24 @@ int prctl(int option, ...) goto errout; #endif +#ifdef CONFIG_SCHED_CAPABILITIES + case PR_CAPS_DROP: + this_task()->group->tg_caps &= ~va_arg(ap, int); + break; + + case PR_CAPS_GET: + va_end(ap); + return this_task()->group->tg_caps; +#endif + default: serr("ERROR: Unrecognized option: %d\n", option); errcode = EINVAL; goto errout; } - /* Not reachable unless CONFIG_TASK_NAME_SIZE is > 0. NOTE: This might - * change if additional commands are supported. - */ - -#if CONFIG_TASK_NAME_SIZE > 0 va_end(ap); return OK; -#endif errout: va_end(ap);