This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit e70cd6bf455f496c2cd3ff754e8269c998d84a9e
Author: Royyan Zahir <[email protected]>
AuthorDate: Fri Oct 2 06:56:34 2026 +0400

    sched: process capabilities
    
    A task group holds PR_CAP_RAWIO, PR_CAP_SPAWN and PR_CAP_ADMIN, inherits
    them from its creator and can only drop them. Every build: the kernel and
    init start with all three, so nothing changes until a task drops one.
    CONFIG_SCHED_CAPABILITIES, off with DEFAULT_SMALL, lets a board short of
    flash leave the checks out.
    
    Signed-off-by: Royyan Zahir <[email protected]>
---
 include/nuttx/sched.h      |  8 ++++++++
 include/sys/prctl.h        |  7 +++++++
 sched/Kconfig              | 11 +++++++++++
 sched/group/group_create.c |  4 ++++
 sched/init/nx_start.c      |  1 +
 sched/task/task_prctl.c    | 16 ++++++++++------
 6 files changed, 41 insertions(+), 6 deletions(-)

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 <stdbool.h>
 #include <stdint.h>
 #include <sched.h>
+#include <sys/prctl.h>
 #include <signal.h>
 #include <pthread.h>
 #include <time.h>
@@ -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);

Reply via email to