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


The following commit(s) were added to refs/heads/master by this push:
     new 6e979f841b0 fs/procfs: fix incorrect environ read for another task 
under CONFIG_ARCH_ADDRENV
6e979f841b0 is described below

commit 6e979f841b0e9881fe5fb01f76319a5211ef5acc
Author: liang.huang <[email protected]>
AuthorDate: Fri Jul 10 11:07:43 2026 +0800

    fs/procfs: fix incorrect environ read for another task under 
CONFIG_ARCH_ADDRENV
    
    Reading /proc/<pid>/group/env for another task dereferenced tg_envp
    under the caller's own address environment instead of the target
    task's, since tg_envp lives in the target's user heap. Switch to the
    target's address environment around the traversal, and to the
    caller's own environment only around the copy into the caller's
    buffer.
    
    Signed-off-by: liang.huang <[email protected]>
---
 fs/procfs/fs_procfsproc.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c
index 53398931fa6..6b515b182e7 100644
--- a/fs/procfs/fs_procfsproc.c
+++ b/fs/procfs/fs_procfsproc.c
@@ -46,6 +46,7 @@
 #  include <time.h>
 #endif
 
+#include <nuttx/addrenv.h>
 #include <nuttx/arch.h>
 #include <nuttx/nuttx.h>
 #include <nuttx/irq.h>
@@ -155,6 +156,9 @@ struct proc_envinfo_s
   size_t buflen;
   size_t remaining;
   size_t totalsize;
+#ifdef CONFIG_ARCH_ADDRENV
+  FAR struct tcb_s *tcb;
+#endif
 };
 
 /****************************************************************************
@@ -1433,9 +1437,18 @@ static int proc_groupenv_callback(FAR void *arg, FAR 
const char *pair)
   size_t linesize;
   size_t copysize;
   int namelen;
+#ifdef CONFIG_ARCH_ADDRENV
+  FAR struct addrenv_s *targetenv;
+#endif
 
   DEBUGASSERT(arg != NULL && pair != NULL);
 
+  /* This callback is invoked by env_foreach() with info->tcb's own address
+   * environment selected, since "pair" points into info->tcb's user heap
+   * (tg_envp).  Parse "pair" and format the result into the kernel-heap-
+   * backed procfile->line first, all done under info->tcb's environment.
+   */
+
   /* Parse the name from the name/value pair */
 
   value  = NULL;
@@ -1470,10 +1483,31 @@ static int proc_groupenv_callback(FAR void *arg, FAR 
const char *pair)
   linesize        = procfs_snprintf(info->procfile->line,
                                     STATUS_LINELEN, "%s=%s\n",
                                     name, value);
+
+  /* info->buffer is the caller's receive buffer, not info->tcb's, so
+   * switch back to the caller's own address environment before touching
+   * it, then switch back to info->tcb's so the next env_foreach()
+   * iteration can dereference the next tg_envp[] entry correctly.
+   */
+
+#ifdef CONFIG_ARCH_ADDRENV
+  if (info->tcb->addrenv_own != NULL)
+    {
+      addrenv_select(nxsched_self()->addrenv_own, &targetenv);
+    }
+#endif
+
   copysize        = procfs_memcpy(info->procfile->line, linesize,
                                   info->buffer, info->remaining,
                                   &info->offset);
 
+#ifdef CONFIG_ARCH_ADDRENV
+  if (info->tcb->addrenv_own != NULL)
+    {
+      addrenv_restore(targetenv);
+    }
+#endif
+
   info->totalsize += copysize;
   info->buffer    += copysize;
   info->remaining -= copysize;
@@ -1498,6 +1532,9 @@ static ssize_t proc_groupenv(FAR struct proc_file_s 
*procfile,
 {
   FAR struct task_group_s *group = tcb->group;
   struct proc_envinfo_s info;
+#ifdef CONFIG_ARCH_ADDRENV
+  FAR struct addrenv_s *oldenv;
+#endif
 
   DEBUGASSERT(group != NULL);
 
@@ -1509,10 +1546,37 @@ static ssize_t proc_groupenv(FAR struct proc_file_s 
*procfile,
   info.buflen     = buflen;
   info.remaining  = buflen;
   info.totalsize  = 0;
+#ifdef CONFIG_ARCH_ADDRENV
+  info.tcb        = tcb;
+#endif
+
+  /* tg_envp holds addresses in tcb's own address space.  Temporarily
+   * switch to it so the strings it points to are actually reachable,
+   * since the caller (e.g. nsh reading another task's /proc node) may
+   * be running under a different address environment.  The caller's own
+   * environment is recovered on demand via nxsched_self()->addrenv_own
+   * in proc_groupenv_callback(), since whichever task runs that callback
+   * is by definition the caller.
+   */
+
+#ifdef CONFIG_ARCH_ADDRENV
+  if (tcb->addrenv_own != NULL)
+    {
+      addrenv_select(tcb->addrenv_own, &oldenv);
+    }
+#endif
 
   /* Generate output for each environment variable */
 
   env_foreach(group, proc_groupenv_callback, &info);
+
+#ifdef CONFIG_ARCH_ADDRENV
+  if (tcb->addrenv_own != NULL)
+    {
+      addrenv_restore(oldenv);
+    }
+#endif
+
   return info.totalsize;
 }
 #endif

Reply via email to