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 cc48013050c2fdd0c76503505b18bb4590511fb7
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Oct 18 20:06:04 2026 +0200

    sched/group: Keep resource limits per process.
    
    setrlimit() kept nothing and returned OK, and getrlimit() returned fixed
    values.  So a limit that a program or a shell set had no effect.
    
    Keep RLIMIT_STACK and RLIMIT_NOFILE in the task group, and make
    getrlimit() and setrlimit() system calls that read and write them, as
    the limits must not be in memory that the process can change.  A new
    process gets the limits of its parent.  The defaults are no stack limit
    and OPEN_MAX open files.  setrlimit() fails with EINVAL for a resource
    that NuttX does not enforce, or for a soft limit above the hard limit,
    and with EPERM when an unprivileged process raises a hard limit or when
    the limit of open files is above OPEN_MAX.  getrlimit() reports the
    resources that NuttX does not limit as RLIM_INFINITY.
    sysconf(_SC_OPEN_MAX) returns the RLIMIT_NOFILE soft limit, as POSIX
    says.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 include/nuttx/sched.h            |   6 ++
 include/sys/syscall_lookup.h     |   2 +
 libs/libc/unistd/CMakeLists.txt  |   2 -
 libs/libc/unistd/Make.defs       |   3 +-
 libs/libc/unistd/lib_getrlimit.c |  93 ----------------
 libs/libc/unistd/lib_setrlimit.c |  55 ----------
 libs/libc/unistd/lib_sysconf.c   |  14 ++-
 sched/group/CMakeLists.txt       |   1 +
 sched/group/Make.defs            |   2 +-
 sched/group/group.h              |   2 +
 sched/group/group_create.c       |   4 +
 sched/group/group_rlimit.c       | 221 +++++++++++++++++++++++++++++++++++++++
 syscall/syscall.csv              |   2 +
 13 files changed, 253 insertions(+), 154 deletions(-)

diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index cf08f12e2a7..e77cd69ef84 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -30,6 +30,7 @@
 #include <nuttx/config.h>
 
 #include <sys/types.h>
+#include <sys/resource.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <sched.h>
@@ -462,6 +463,11 @@ struct task_group_s
   uint8_t tg_flags;                 /* See GROUP_FLAG_* definitions            
 */
   uint8_t tg_caps;                  /* See PR_CAP_* definitions                
 */
 
+  /* Resource limits (getrlimit() and setrlimit()) **************************/
+
+  struct rlimit tg_rlimit_stack;    /* RLIMIT_STACK                            
 */
+  struct rlimit tg_rlimit_nofile;   /* RLIMIT_NOFILE                           
 */
+
   /* User identity (POSIX real, effective, and saved-set IDs) ***************/
 
 #ifdef CONFIG_SCHED_USER_IDENTITY
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index 5bbd5b017b8..d5153628194 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -56,6 +56,8 @@ SYSCALL_LOOKUP(nxsched_get_stackinfo,      2)
 #endif
 
 SYSCALL_LOOKUP(sysinfo,                    1)
+SYSCALL_LOOKUP(getrlimit,                  2)
+SYSCALL_LOOKUP(setrlimit,                  2)
 
 SYSCALL_LOOKUP(gethostname,                2)
 SYSCALL_LOOKUP(sethostname,                2)
diff --git a/libs/libc/unistd/CMakeLists.txt b/libs/libc/unistd/CMakeLists.txt
index 06ed405a890..f2bce74698f 100644
--- a/libs/libc/unistd/CMakeLists.txt
+++ b/libs/libc/unistd/CMakeLists.txt
@@ -49,8 +49,6 @@ set(SRCS
     lib_getrusage.c
     lib_utime.c
     lib_utimes.c
-    lib_setrlimit.c
-    lib_getrlimit.c
     lib_setpriority.c
     lib_getpriority.c
     lib_futimes.c
diff --git a/libs/libc/unistd/Make.defs b/libs/libc/unistd/Make.defs
index 20a4e048786..2d9110ad4b0 100644
--- a/libs/libc/unistd/Make.defs
+++ b/libs/libc/unistd/Make.defs
@@ -29,8 +29,7 @@ CSRCS += lib_getopt_long.c lib_getopt_longonly.c 
lib_getoptvars.c lib_getoptargp
 CSRCS += lib_getopterrp.c lib_getoptindp.c lib_getoptoptp.c lib_times.c
 CSRCS += lib_alarm.c lib_fstatvfs.c lib_statvfs.c lib_sleep.c lib_nice.c
 CSRCS += lib_getrusage.c lib_utime.c lib_utimes.c lib_getdtablesize.c
-CSRCS += lib_getpagesize.c
-CSRCS += lib_setrlimit.c lib_getrlimit.c lib_setpriority.c lib_getpriority.c
+CSRCS += lib_getpagesize.c lib_setpriority.c lib_getpriority.c
 CSRCS += lib_futimes.c lib_lutimes.c lib_gethostname.c lib_sethostname.c
 CSRCS += lib_fchownat.c lib_linkat.c lib_readlinkat.c lib_symlinkat.c
 CSRCS += lib_unlinkat.c lib_usleep.c lib_getpgrp.c lib_getpgid.c
diff --git a/libs/libc/unistd/lib_getrlimit.c b/libs/libc/unistd/lib_getrlimit.c
deleted file mode 100644
index 1e4850aafc5..00000000000
--- a/libs/libc/unistd/lib_getrlimit.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/****************************************************************************
- * libs/libc/unistd/lib_getrlimit.c
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <string.h>
-#include <errno.h>
-
-#include <sys/resource.h>
-#include <pthread.h>
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: getrlimit
- *
- * Description:
- *   The getrlimit() and setrlimit() system calls get and
- *   set resource limits respectively.
- *
- ****************************************************************************/
-
-int getrlimit(int resource, FAR struct rlimit *rlp)
-{
-  UNUSED(resource);
-
-  if (rlp == NULL)
-    {
-      set_errno(EINVAL);
-      return ERROR;
-    }
-
-  /* This is a dummy realization to make the compiler happy */
-
-  memset(rlp, 0, sizeof(*rlp));
-
-  switch (resource)
-    {
-      case RLIMIT_NOFILE:
-        {
-          rlp->rlim_cur = OPEN_MAX;
-          rlp->rlim_max = OPEN_MAX;
-        }
-        break;
-      case RLIMIT_STACK:
-        {
-          rlp->rlim_cur = PTHREAD_STACK_DEFAULT;
-          rlp->rlim_max = RLIM_INFINITY;
-        }
-        break;
-      case RLIMIT_RTPRIO:
-        {
-          rlp->rlim_cur = SCHED_PRIORITY_DEFAULT;
-          rlp->rlim_max = SCHED_PRIORITY_MAX;
-        }
-        break;
-      case RLIMIT_RTTIME:
-        {
-          rlp->rlim_cur = UINT32_MAX;
-          rlp->rlim_max = UINT32_MAX;
-        }
-        break;
-      default:
-        break;
-    }
-
-  return OK;
-}
diff --git a/libs/libc/unistd/lib_setrlimit.c b/libs/libc/unistd/lib_setrlimit.c
deleted file mode 100644
index 6f21c9110da..00000000000
--- a/libs/libc/unistd/lib_setrlimit.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
- * libs/libc/unistd/lib_setrlimit.c
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-
-#include <string.h>
-#include <errno.h>
-
-#include <sys/resource.h>
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: setrlimit
- *
- * Description:
- *   The getrlimit() and setrlimit() system calls get and
- *   set resource limits respectively.
- *
- ****************************************************************************/
-
-int setrlimit(int resource, FAR const struct rlimit *rlp)
-{
-  /* This is a dummy realization to make the compiler happy */
-
-  UNUSED(resource);
-  UNUSED(rlp);
-
-  return OK;
-}
diff --git a/libs/libc/unistd/lib_sysconf.c b/libs/libc/unistd/lib_sysconf.c
index f05e171cb7b..840279d5ad6 100644
--- a/libs/libc/unistd/lib_sysconf.c
+++ b/libs/libc/unistd/lib_sysconf.c
@@ -28,6 +28,7 @@
 
 #include <nuttx/atexit.h>
 
+#include <sys/resource.h>
 #include <unistd.h>
 #include <limits.h>
 #include <sched.h>
@@ -245,7 +246,18 @@ long sysconf(int name)
         return ARG_MAX;
 
       case _SC_OPEN_MAX:
-        return OPEN_MAX;
+        {
+          struct rlimit rlim;
+
+          /* The soft limit of the process, which setrlimit() can change */
+
+          if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
+            {
+              return rlim.rlim_cur;
+            }
+
+          return OPEN_MAX;
+        }
 
       case _SC_NGROUPS_MAX:
         return NGROUPS_MAX;
diff --git a/sched/group/CMakeLists.txt b/sched/group/CMakeLists.txt
index 5353552c849..58919779e4e 100644
--- a/sched/group/CMakeLists.txt
+++ b/sched/group/CMakeLists.txt
@@ -22,6 +22,7 @@
 
 set(SRCS
     group_create.c
+    group_rlimit.c
     group_join.c
     group_leave.c
     group_setupidlefiles.c
diff --git a/sched/group/Make.defs b/sched/group/Make.defs
index b2605e53fe5..e060dcc8c66 100644
--- a/sched/group/Make.defs
+++ b/sched/group/Make.defs
@@ -20,7 +20,7 @@
 #
 ############################################################################
 
-CSRCS += group_create.c group_join.c group_leave.c
+CSRCS += group_create.c group_join.c group_leave.c group_rlimit.c
 CSRCS += group_setupidlefiles.c group_setuptaskfiles.c
 CSRCS += group_foreachchild.c group_killchildren.c
 
diff --git a/sched/group/group.h b/sched/group/group.h
index 665ee69ac7b..915997b19f5 100644
--- a/sched/group/group.h
+++ b/sched/group/group.h
@@ -59,6 +59,8 @@ void task_initialize(void);
 /* Task group data structure management */
 
 int  group_allocate(FAR struct tcb_s *tcb, uint8_t ttype);
+void group_init_rlimit(FAR struct task_group_s *group,
+                       FAR struct task_group_s *parent);
 void group_initialize(FAR struct tcb_s *tcb);
 #ifndef CONFIG_DISABLE_PTHREAD
 void group_bind(FAR struct tcb_s *tcb);
diff --git a/sched/group/group_create.c b/sched/group/group_create.c
index 5febd80e11b..aa20c811718 100644
--- a/sched/group/group_create.c
+++ b/sched/group/group_create.c
@@ -254,6 +254,10 @@ int group_allocate(FAR struct tcb_s *tcb, uint8_t ttype)
   group->tg_caps = this_task()->group != NULL ?
                    this_task()->group->tg_caps : PR_CAP_ALL;
 
+  /* Inherit the resource limits from the parent task group */
+
+  group_init_rlimit(group, this_task()->group);
+
   /* Initialize file descriptors for the TCB */
 
   fdlist_init(&group->tg_fdlist);
diff --git a/sched/group/group_rlimit.c b/sched/group/group_rlimit.c
new file mode 100644
index 00000000000..730c8def329
--- /dev/null
+++ b/sched/group/group_rlimit.c
@@ -0,0 +1,221 @@
+/****************************************************************************
+ * sched/group/group_rlimit.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/resource.h>
+#include <errno.h>
+#include <limits.h>
+#include <sched.h>
+#include <stdint.h>
+
+#include <nuttx/sched.h>
+
+#include "group/group.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: group_rlimit
+ *
+ * Description:
+ *   Return the limit of a task group for a resource that NuttX enforces,
+ *   or NULL for any other resource.
+ *
+ ****************************************************************************/
+
+static inline FAR struct rlimit *group_rlimit(FAR struct task_group_s *group,
+                                              int resource)
+{
+  switch (resource)
+    {
+      case RLIMIT_STACK:
+        return &group->tg_rlimit_stack;
+
+      case RLIMIT_NOFILE:
+        return &group->tg_rlimit_nofile;
+
+      default:
+        return NULL;
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: group_init_rlimit
+ *
+ * Description:
+ *   Give a new task group the resource limits of its parent, or the
+ *   defaults if it has none: no stack limit and OPEN_MAX open files.  At
+ *   boot, the idle task is its own parent: it gets the defaults.
+ *
+ ****************************************************************************/
+
+void group_init_rlimit(FAR struct task_group_s *group,
+                       FAR struct task_group_s *parent)
+{
+  if (parent != NULL && parent != group)
+    {
+      group->tg_rlimit_stack  = parent->tg_rlimit_stack;
+      group->tg_rlimit_nofile = parent->tg_rlimit_nofile;
+    }
+  else
+    {
+      group->tg_rlimit_stack.rlim_cur  = RLIM_INFINITY;
+      group->tg_rlimit_stack.rlim_max  = RLIM_INFINITY;
+      group->tg_rlimit_nofile.rlim_cur = OPEN_MAX;
+      group->tg_rlimit_nofile.rlim_max = OPEN_MAX;
+    }
+}
+
+/****************************************************************************
+ * Name: getrlimit
+ *
+ * Description:
+ *   Return the soft and hard limit of a resource of the calling process.
+ *   RLIMIT_STACK and RLIMIT_NOFILE are limits of the process.  The
+ *   resources that NuttX does not limit are reported as RLIM_INFINITY.
+ *
+ * Input Parameters:
+ *   resource - The resource, RLIMIT_*.
+ *   rlp      - The location that receives the limits.
+ *
+ * Returned Value:
+ *   Zero (OK) on success.  On failure, -1 (ERROR) is returned and errno is
+ *   set to EINVAL: rlp is NULL or resource is not valid.
+ *
+ ****************************************************************************/
+
+int getrlimit(int resource, FAR struct rlimit *rlp)
+{
+  FAR struct rlimit *limit;
+
+  if (rlp == NULL)
+    {
+      set_errno(EINVAL);
+      return ERROR;
+    }
+
+  limit = group_rlimit(nxsched_self()->group, resource);
+  if (limit != NULL)
+    {
+      *rlp = *limit;
+      return OK;
+    }
+
+  switch (resource)
+    {
+      case RLIMIT_CORE:
+      case RLIMIT_CPU:
+      case RLIMIT_DATA:
+      case RLIMIT_FSIZE:
+      case RLIMIT_AS:
+      case RLIMIT_MEMLOCK:
+        rlp->rlim_cur = RLIM_INFINITY;
+        rlp->rlim_max = RLIM_INFINITY;
+        break;
+
+      case RLIMIT_NICE:
+        rlp->rlim_cur = 0;
+        rlp->rlim_max = 0;
+        break;
+
+      case RLIMIT_RTPRIO:
+        rlp->rlim_cur = SCHED_PRIORITY_DEFAULT;
+        rlp->rlim_max = SCHED_PRIORITY_MAX;
+        break;
+
+      case RLIMIT_RTTIME:
+        rlp->rlim_cur = UINT32_MAX;
+        rlp->rlim_max = UINT32_MAX;
+        break;
+
+      default:
+        set_errno(EINVAL);
+        return ERROR;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: setrlimit
+ *
+ * Description:
+ *   Set the soft and hard limit of a resource of the calling process.  The
+ *   process gives its limits to the processes that it creates.  NuttX
+ *   enforces RLIMIT_STACK (the default stack size of new threads and
+ *   programs) and RLIMIT_NOFILE (the number of open files).
+ *
+ * Input Parameters:
+ *   resource - RLIMIT_STACK or RLIMIT_NOFILE.
+ *   rlp      - The new limits.
+ *
+ * Returned Value:
+ *   Zero (OK) on success.  On failure, -1 (ERROR) is returned and errno is
+ *   set:
+ *
+ *     EINVAL - rlp is NULL, the soft limit is above the hard limit, or
+ *              NuttX does not enforce the resource.
+ *     EPERM  - The hard limit is raised without privileges, or the limit
+ *              of open files is above OPEN_MAX.
+ *
+ ****************************************************************************/
+
+int setrlimit(int resource, FAR const struct rlimit *rlp)
+{
+  FAR struct task_group_s *group = nxsched_self()->group;
+  FAR struct rlimit *limit;
+
+  limit = group_rlimit(group, resource);
+  if (rlp == NULL || limit == NULL || rlp->rlim_cur > rlp->rlim_max)
+    {
+      set_errno(EINVAL);
+      return ERROR;
+    }
+
+  if (resource == RLIMIT_NOFILE && rlp->rlim_max > OPEN_MAX)
+    {
+      set_errno(EPERM);
+      return ERROR;
+    }
+
+#ifdef CONFIG_SCHED_USER_IDENTITY
+  if (rlp->rlim_max > limit->rlim_max && group->tg_euid != 0)
+    {
+      set_errno(EPERM);
+      return ERROR;
+    }
+#endif
+
+  *limit = *rlp;
+  return OK;
+}
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index 873629b2d89..bcb29d3c853 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -48,6 +48,7 @@
 
"getitimer","sys/time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","int","FAR
 struct itimerval *"
 "getpeername","sys/socket.h","defined(CONFIG_NET)","int","int","FAR struct 
sockaddr *","FAR socklen_t *"
 "getppid","unistd.h","defined(CONFIG_SCHED_HAVE_PARENT)","pid_t"
+"getrlimit","sys/resource.h","","int","int","FAR struct rlimit *"
 "getsockname","sys/socket.h","defined(CONFIG_NET)","int","int","FAR struct 
sockaddr *","FAR socklen_t *"
 "getsockopt","sys/socket.h","defined(CONFIG_NET)","int","int","int","int","FAR 
void *","FAR socklen_t *"
 "gettimeofday","sys/time.h","","int","FAR struct timeval *","FAR struct 
timezone *"
@@ -166,6 +167,7 @@
 "setgid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","gid_t"
 "sethostname","unistd.h","","int","FAR const char *","size_t"
 
"setitimer","sys/time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","int","FAR
 const struct itimerval *","FAR struct itimerval *"
+"setrlimit","sys/resource.h","","int","int","FAR const struct rlimit *"
 "setsockopt","sys/socket.h","defined(CONFIG_NET) && 
defined(CONFIG_NET_SOCKOPTS)","int","int","int","int","FAR const void 
*","socklen_t"
 "settimeofday","sys/time.h","","int","FAR const struct timeval *","FAR const 
struct timezone *"
 "setuid","unistd.h","defined(CONFIG_SCHED_USER_IDENTITY)","int","uid_t"

Reply via email to