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 e1dc2741b39c524121d44b7484c48d98039a489f
Author: guoshichao <[email protected]>
AuthorDate: Mon Nov 10 21:58:29 2025 +0800

    environ: change the tg_en* from task_group_s to task_info_s
    
    Since tg_envp is placed in task_info_s, both tg_envp itself and the
    memory it points to (group_malloc) are userspace memory.
    There's no need to switch to kernel mode to access tg_env, which can
    improve access speed.
    
    Signed-off-by: guoshichao <[email protected]>
    (cherry picked from commit e60e6de82f6bf1e72139fcdba73ff3e26b951869
     in https://github.com/open-vela/nuttx)
    
    Port to Apache master: env_sanitize_secure() (env_secureexec.c, added
    later on master) also reads the environment from the task info.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 include/nuttx/sched.h             |  8 --------
 include/nuttx/tls.h               |  7 +++++++
 sched/environ/env_dup.c           | 17 ++++++++++------
 sched/environ/env_findvar.c       | 13 +++++++++----
 sched/environ/env_foreach.c       | 14 ++++++++-----
 sched/environ/env_getenv.c        |  5 ++++-
 sched/environ/env_getenvironptr.c |  4 +++-
 sched/environ/env_release.c       | 20 +++++++++++--------
 sched/environ/env_removevar.c     | 41 +++++++++++++++++++++++----------------
 sched/environ/env_secureexec.c    | 11 ++++++++---
 sched/environ/env_setenv.c        | 33 ++++++++++++++++++-------------
 sched/group/group_leave.c         |  8 ++++----
 12 files changed, 110 insertions(+), 71 deletions(-)

diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index ddb650e2d9f..76ea460379e 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -535,14 +535,6 @@ struct task_group_s
   sigset_t tg_sigdefault;           /* Set of signals set to the default 
action */
 #endif
 
-#ifndef CONFIG_DISABLE_ENVIRON
-  /* Environment variables **************************************************/
-
-  FAR char **tg_envp;               /* Allocated environment strings        */
-  ssize_t    tg_envpc;              /* Maximum entries of environment array */
-  ssize_t    tg_envc;               /* Number of environment strings        */
-#endif
-
 #ifndef CONFIG_DISABLE_POSIX_TIMERS
   /* Interval timer *********************************************************/
 
diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h
index 256bfd15a14..e0464b3248e 100644
--- a/include/nuttx/tls.h
+++ b/include/nuttx/tls.h
@@ -162,6 +162,13 @@ struct task_info_s
   struct list_node ta_atfork; /* Holds the pthread_atfork_s list */
 #endif
   pid_t ta_pid; /* Process ID */
+#ifndef CONFIG_DISABLE_ENVIRON
+  /* Environment variables **************************************************/
+
+  FAR char            **ta_envp;    /* Allocated environment strings        */
+  ssize_t               ta_envpc;   /* Maximum entries of environment array */
+  ssize_t               ta_envc;    /* Number of environment strings        */
+#endif
 };
 
 /* struct tls_cleanup_s *****************************************************/
diff --git a/sched/environ/env_dup.c b/sched/environ/env_dup.c
index ae58b2a63f8..d2f16bc8dd0 100644
--- a/sched/environ/env_dup.c
+++ b/sched/environ/env_dup.c
@@ -35,6 +35,8 @@
 #include <errno.h>
 
 #include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/tls.h>
 
 #include "sched/sched.h"
 #include "environ/environ.h"
@@ -65,16 +67,19 @@
 
 int env_dup(FAR struct task_group_s *group, FAR char * const *envcp)
 {
+  FAR struct task_info_s *info;
   FAR char **envp = NULL;
   size_t envc = 0;
   size_t size;
   int ret = OK;
 
-  DEBUGASSERT(group != NULL);
+  DEBUGASSERT(group != NULL && group->tg_info != NULL);
+
+  info = group->tg_info;
 
   /* Is there an environment ? */
 
-  if (envcp != NULL && group->tg_envp == NULL)
+  if (envcp != NULL && info->ta_envp == NULL)
     {
       /* Pre-emption must be disabled throughout the following because the
        * environment may be shared.
@@ -89,8 +94,8 @@ int env_dup(FAR struct task_group_s *group, FAR char * const 
*envcp)
           envc++;
         }
 
-      group->tg_envc = envc;
-      group->tg_envpc = (envc + SCHED_ENVIRON_RESERVED + 1);
+      info->ta_envc = envc;
+      info->ta_envpc = (envc + SCHED_ENVIRON_RESERVED + 1);
 
       /* A special case is that the parent has an "empty" environment
        * allocation, i.e., there is an allocation in place but it
@@ -101,7 +106,7 @@ int env_dup(FAR struct task_group_s *group, FAR char * 
const *envcp)
         {
           /* There is an environment, duplicate it */
 
-          envp = group_malloc(group, sizeof(*envp) * group->tg_envpc);
+          envp = group_malloc(group, sizeof(*envp) * info->ta_envpc);
           if (envp == NULL)
             {
               /* The parent's environment can not be inherited due to a
@@ -140,7 +145,7 @@ int env_dup(FAR struct task_group_s *group, FAR char * 
const *envcp)
 
       /* Save the child environment allocation. */
 
-      group->tg_envp = envp;
+      info->ta_envp = envp;
       nxrmutex_unlock(&group->tg_mutex);
     }
 
diff --git a/sched/environ/env_findvar.c b/sched/environ/env_findvar.c
index 0a2f5413420..a0879a5454a 100644
--- a/sched/environ/env_findvar.c
+++ b/sched/environ/env_findvar.c
@@ -33,6 +33,8 @@
 #include <sched.h>
 #include <assert.h>
 
+#include <nuttx/tls.h>
+
 #include "environ/environ.h"
 
 /****************************************************************************
@@ -87,22 +89,25 @@ static bool env_cmpname(const char *pszname, const char 
*peqname)
 
 ssize_t env_findvar(FAR struct task_group_s *group, FAR const char *pname)
 {
+  FAR struct task_info_s *info;
   ssize_t i;
 
   /* Verify input parameters */
 
-  DEBUGASSERT(group != NULL && pname != NULL);
+  DEBUGASSERT(group != NULL && group->tg_info != NULL && pname != NULL);
+
+  info = group->tg_info;
 
-  if (group->tg_envp == NULL)
+  if (info->ta_envp == NULL)
     {
       return -ENOENT;
     }
 
   /* Search for a name=value string with matching name */
 
-  for (i = 0; group->tg_envp[i] != NULL; i++)
+  for (i = 0; info->ta_envp[i] != NULL; i++)
     {
-      if (env_cmpname(pname, group->tg_envp[i]))
+      if (env_cmpname(pname, info->ta_envp[i]))
         {
           return i;
         }
diff --git a/sched/environ/env_foreach.c b/sched/environ/env_foreach.c
index 5569bc2ca25..b552549bc4d 100644
--- a/sched/environ/env_foreach.c
+++ b/sched/environ/env_foreach.c
@@ -34,6 +34,7 @@
 #include <assert.h>
 
 #include <nuttx/environ.h>
+#include <nuttx/tls.h>
 
 #include "environ/environ.h"
 
@@ -67,23 +68,26 @@ int env_foreach(FAR struct task_group_s *group,
                 env_foreach_t cb,
                 FAR void *arg)
 {
+  FAR struct task_info_s *info;
   int ret = OK;
   size_t i;
 
   /* Verify input parameters */
 
-  DEBUGASSERT(group != NULL && cb != NULL);
+  DEBUGASSERT(group != NULL && group->tg_info != NULL && cb != NULL);
 
-  if (group->tg_envp == NULL)
+  info = group->tg_info;
+
+  if (info->ta_envp == NULL)
     {
       return ret;
     }
 
-  for (i = 0; group->tg_envp[i] != NULL; i++)
+  for (i = 0; info->ta_envp[i] != NULL; i++)
     {
       /* Perform the callback */
 
-      ret = cb(arg, group->tg_envp[i]);
+      ret = cb(arg, info->ta_envp[i]);
 
       /* Terminate the traversal early if the callback so requests by
        * returning a non-zero value.
@@ -95,7 +99,7 @@ int env_foreach(FAR struct task_group_s *group,
         }
     }
 
-  DEBUGASSERT(ret != OK || group->tg_envc == i);
+  DEBUGASSERT(ret != OK || info->ta_envc == i);
 
   return ret;
 }
diff --git a/sched/environ/env_getenv.c b/sched/environ/env_getenv.c
index 248fc4198f3..34142490f7a 100644
--- a/sched/environ/env_getenv.c
+++ b/sched/environ/env_getenv.c
@@ -33,6 +33,9 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#include <nuttx/mutex.h>
+#include <nuttx/tls.h>
+
 #include "sched/sched.h"
 #include "environ/environ.h"
 
@@ -95,7 +98,7 @@ FAR char *getenv(FAR const char *name)
 
   /* It does!  Get the value sub-string from the name=value string */
 
-  pvalue = strchr(group->tg_envp[ret], '=');
+  pvalue = strchr(group->tg_info->ta_envp[ret], '=');
   if (pvalue == NULL)
     {
       nxrmutex_unlock(&group->tg_mutex);
diff --git a/sched/environ/env_getenvironptr.c 
b/sched/environ/env_getenvironptr.c
index d1e930f566e..bf5be54bc30 100644
--- a/sched/environ/env_getenvironptr.c
+++ b/sched/environ/env_getenvironptr.c
@@ -30,6 +30,8 @@
 
 #include <sched.h>
 #include <stdlib.h>
+#include <nuttx/tls.h>
+
 #include "sched/sched.h"
 
 #undef get_environ_ptr
@@ -58,7 +60,7 @@ FAR char **get_environ_ptr(void)
 {
   FAR struct tcb_s *tcb = this_task();
 
-  return tcb->group->tg_envp;
+  return tcb->group->tg_info->ta_envp;
 }
 
 #endif /* CONFIG_DISABLE_ENVIRON */
diff --git a/sched/environ/env_release.c b/sched/environ/env_release.c
index 6ada8bf7908..d9b090662c7 100644
--- a/sched/environ/env_release.c
+++ b/sched/environ/env_release.c
@@ -33,6 +33,7 @@
 #include <errno.h>
 
 #include <nuttx/kmalloc.h>
+#include <nuttx/tls.h>
 
 #include "environ/environ.h"
 
@@ -63,31 +64,34 @@
 
 void env_release(FAR struct task_group_s *group)
 {
+  FAR struct task_info_s *info;
   int i;
 
-  DEBUGASSERT(group != NULL);
+  DEBUGASSERT(group != NULL && group->tg_info != NULL);
 
-  if (group->tg_envp)
+  info = group->tg_info;
+
+  if (info->ta_envp)
     {
       /* Free any allocate environment strings */
 
-      for (i = 0; group->tg_envp[i] != NULL; i++)
+      for (i = 0; info->ta_envp[i] != NULL; i++)
         {
-          group_free(group, group->tg_envp[i]);
+          group_free(group, info->ta_envp[i]);
         }
 
       /* Free the environment */
 
-      group_free(group, group->tg_envp);
+      group_free(group, info->ta_envp);
     }
 
   /* In any event, make sure that all environment-related variables in the
    * task group structure are reset to initial values.
    */
 
-  group->tg_envp  = NULL;
-  group->tg_envpc = 0;
-  group->tg_envc  = 0;
+  info->ta_envp  = NULL;
+  info->ta_envpc = 0;
+  info->ta_envc  = 0;
 }
 
 #endif /* CONFIG_DISABLE_ENVIRON */
diff --git a/sched/environ/env_removevar.c b/sched/environ/env_removevar.c
index 5a08042ac4e..fd6eb0ef994 100644
--- a/sched/environ/env_removevar.c
+++ b/sched/environ/env_removevar.c
@@ -33,6 +33,7 @@
 #include <assert.h>
 
 #include <nuttx/kmalloc.h>
+#include <nuttx/tls.h>
 
 #include "environ/environ.h"
 
@@ -63,43 +64,49 @@
 
 void env_removevar(FAR struct task_group_s *group, ssize_t index)
 {
-  DEBUGASSERT(group != NULL && index >= 0 && index < group->tg_envc);
+  FAR struct task_info_s *info;
+
+  DEBUGASSERT(group != NULL && group->tg_info != NULL);
+
+  info = group->tg_info;
+
+  DEBUGASSERT(index >= 0 && index < info->ta_envc);
 
   /* Free the allocate environment string */
 
-  group_free(group, group->tg_envp[index]);
+  group_free(group, info->ta_envp[index]);
 
   /* Exchange the last env and the index env */
 
-  group->tg_envc--;
-  if (index == group->tg_envc)
+  info->ta_envc--;
+  if (index == info->ta_envc)
     {
-      group->tg_envp[index] = NULL;
+      info->ta_envp[index] = NULL;
     }
   else
     {
-      group->tg_envp[index] = group->tg_envp[group->tg_envc];
-      group->tg_envp[group->tg_envc] = NULL;
+      info->ta_envp[index] = info->ta_envp[info->ta_envc];
+      info->ta_envp[info->ta_envc] = NULL;
     }
 
   /* Free the old environment (if there was one) */
 
-  if (group->tg_envc == 0)
+  if (info->ta_envc == 0)
     {
-      group_free(group, group->tg_envp);
-      group->tg_envp = NULL;
-      group->tg_envpc = 0;
+      group_free(group, info->ta_envp);
+      info->ta_envp = NULL;
+      info->ta_envpc = 0;
     }
-  else if (group->tg_envc <=
-           (group->tg_envpc - SCHED_ENVIRON_RESERVED * 2))
+  else if (info->ta_envc <=
+           (info->ta_envpc - SCHED_ENVIRON_RESERVED * 2))
     {
       /* Reallocate the environment to reclaim a little memory */
 
-      group->tg_envpc = group->tg_envc + SCHED_ENVIRON_RESERVED + 1;
+      info->ta_envpc = info->ta_envc + SCHED_ENVIRON_RESERVED + 1;
 
-      group->tg_envp = group_realloc(group, group->tg_envp,
-         sizeof(*group->tg_envp) * group->tg_envpc);
-      DEBUGASSERT(group->tg_envp != NULL);
+      info->ta_envp = group_realloc(group, info->ta_envp,
+         sizeof(*info->ta_envp) * info->ta_envpc);
+      DEBUGASSERT(info->ta_envp != NULL);
     }
 }
 
diff --git a/sched/environ/env_secureexec.c b/sched/environ/env_secureexec.c
index 5315f496c14..231fd54ba37 100644
--- a/sched/environ/env_secureexec.c
+++ b/sched/environ/env_secureexec.c
@@ -31,6 +31,8 @@
 #include <stdlib.h>
 #include <assert.h>
 
+#include <nuttx/tls.h>
+
 #include "sched/sched.h"
 #include "environ/environ.h"
 
@@ -99,15 +101,18 @@ static bool env_is_unsafe(FAR const char *pair)
 #ifdef CONFIG_SCHED_USER_IDENTITY
 void env_sanitize_secure(FAR struct task_group_s *group)
 {
+  FAR struct task_info_s *info;
   ssize_t index;
 
-  DEBUGASSERT(group != NULL);
+  DEBUGASSERT(group != NULL && group->tg_info != NULL);
+
+  info = group->tg_info;
 
   nxrmutex_lock(&group->tg_mutex);
 
-  for (index = group->tg_envc - 1; index >= 0; )
+  for (index = info->ta_envc - 1; index >= 0; )
     {
-      FAR char *pair = group->tg_envp[index];
+      FAR char *pair = info->ta_envp[index];
 
       if (pair != NULL && env_is_unsafe(pair))
         {
diff --git a/sched/environ/env_setenv.c b/sched/environ/env_setenv.c
index ea24bdad99e..115a45a68d6 100644
--- a/sched/environ/env_setenv.c
+++ b/sched/environ/env_setenv.c
@@ -36,6 +36,8 @@
 #include <errno.h>
 
 #include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/tls.h>
 
 #include "sched/sched.h"
 #include "environ/environ.h"
@@ -71,6 +73,7 @@ int setenv(FAR const char *name, FAR const char *value, int 
overwrite)
 {
   FAR struct tcb_s *rtcb;
   FAR struct task_group_s *group;
+  FAR struct task_info_s *info;
   FAR char *pvar;
   FAR char **envp;
   ssize_t envc;
@@ -112,13 +115,15 @@ int setenv(FAR const char *name, FAR const char *value, 
int overwrite)
 
   rtcb  = this_task();
   group = rtcb->group;
-  DEBUGASSERT(group);
+  DEBUGASSERT(group && group->tg_info);
+
+  info = group->tg_info;
 
   nxrmutex_lock(&group->tg_mutex);
 
   /* Check if the variable already exists */
 
-  if (group->tg_envp && (ret = env_findvar(group, name)) >= 0)
+  if (info->ta_envp && (ret = env_findvar(group, name)) >= 0)
     {
       /* It does! Do we have permission to overwrite the existing value? */
 
@@ -140,7 +145,7 @@ int setenv(FAR const char *name, FAR const char *value, int 
overwrite)
 
   /* Check current envirments count */
 
-  DEBUGASSERT(group->tg_envc < SSIZE_MAX);
+  DEBUGASSERT(info->ta_envc < SSIZE_MAX);
 
   /* Get the size of the new name=value string.
    * The +2 is for the '=' and for null terminator
@@ -157,9 +162,9 @@ int setenv(FAR const char *name, FAR const char *value, int 
overwrite)
       goto errout_with_lock;
     }
 
-  envc = group->tg_envc;
+  envc = info->ta_envc;
 
-  if (group->tg_envp == NULL)
+  if (info->ta_envp == NULL)
     {
       envpc = SCHED_ENVIRON_RESERVED + 2;
 
@@ -170,29 +175,29 @@ int setenv(FAR const char *name, FAR const char *value, 
int overwrite)
           goto errout_with_var;
         }
 
-      group->tg_envp  = envp;
-      group->tg_envpc = envpc;
+      info->ta_envp  = envp;
+      info->ta_envpc = envpc;
     }
-  else if (envc >= group->tg_envpc - 1)
+  else if (envc >= info->ta_envpc - 1)
     {
       envpc = envc + SCHED_ENVIRON_RESERVED + 2;
 
-      envp = group_realloc(group, group->tg_envp, sizeof(*envp) * envpc);
+      envp = group_realloc(group, info->ta_envp, sizeof(*envp) * envpc);
       if (envp == NULL)
         {
           ret = ENOMEM;
           goto errout_with_var;
         }
 
-      group->tg_envp  = envp;
-      group->tg_envpc = envpc;
+      info->ta_envp  = envp;
+      info->ta_envpc = envpc;
     }
 
   /* Save the new buffer and count */
 
-  group->tg_envp[envc++] = pvar;
-  group->tg_envp[envc]   = NULL;
-  group->tg_envc = envc;
+  info->ta_envp[envc++] = pvar;
+  info->ta_envp[envc]   = NULL;
+  info->ta_envc = envc;
 
   /* Now, put the new name=value string into the environment buffer */
 
diff --git a/sched/group/group_leave.c b/sched/group/group_leave.c
index 466f44be481..5752d1c4375 100644
--- a/sched/group/group_leave.c
+++ b/sched/group/group_leave.c
@@ -81,6 +81,10 @@ static inline void group_release(FAR struct task_group_s 
*group)
 
   nxrmutex_destroy(&group->tg_mutex);
 
+  /* Release all shared environment variables */
+
+  env_release(group);
+
   task_uninit_info(group);
 
 #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)
@@ -119,10 +123,6 @@ static inline void group_release(FAR struct task_group_s 
*group)
     }
 #endif
 
-  /* Release all shared environment variables */
-
-  env_release(group);
-
   /* Destroy the mm_map list */
 
   mm_map_destroy(&group->tg_mm_map);

Reply via email to