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 4cf4913de12 fs/inode: Keep the close-on-exec flag of descriptors in a 
fork() child
4cf4913de12 is described below

commit 4cf4913de12b1dcfa4129d1ffc65d194c2201edd
Author: Marco Casaroli <[email protected]>
AuthorDate: Mon Nov 2 19:48:41 2026 +0100

    fs/inode: Keep the close-on-exec flag of descriptors in a fork() child
    
    fdlist_copy() gives the child of fork() or vfork() a copy of each
    descriptor without its flags, so FD_CLOEXEC is lost.  POSIX: the child
    inherits the descriptors with their flags.  When the child then calls
    exec(), exec() closes nothing: the new program has every descriptor that
    the caller marked close-on-exec.  For example, a parent that waits for end
    of file on a close-on-exec pipe to see that the child called exec() waits
    until the new program ends.
    
    The copy for fork() now keeps the close-on-exec flag of each descriptor.
    The copies for exec() and posix_spawn() do not change.  The parameter
    cloexec of fdlist_copy() and group_setuptaskfiles() is now exec: it
    tells that the copy is for a new program, not the flag of a descriptor.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 fs/inode/fs_files.c                | 20 ++++++++++++++++----
 include/nuttx/fs/fs.h              |  2 +-
 sched/group/group.h                |  2 +-
 sched/group/group_setuptaskfiles.c |  7 ++++---
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/fs/inode/fs_files.c b/fs/inode/fs_files.c
index be522834f71..479ceb368eb 100644
--- a/fs/inode/fs_files.c
+++ b/fs/inode/fs_files.c
@@ -720,6 +720,14 @@ int file_allocate_from_inode(FAR struct inode *inode, int 
oflags, off_t pos,
  * Description:
  *   Copy parent task's file descriptors to child task.
  *
+ * Input Parameters:
+ *   plist   - The descriptor list of the parent
+ *   clist   - The descriptor list of the child
+ *   actions - The spawn file actions, or NULL
+ *   exec    - True when the child is a new program (exec(), posix_spawn(),
+ *             task_create()): leave out the close-on-exec descriptors.
+ *             False for fork() and vfork(): keep them, with their flag.
+ *
  * Returned Value:
  *   Zero (OK) is returned on success; a negated errno value is returned on
  *   any failure.
@@ -728,7 +736,7 @@ int file_allocate_from_inode(FAR struct inode *inode, int 
oflags, off_t pos,
 
 int fdlist_copy(FAR struct fdlist *plist, FAR struct fdlist *clist,
                 FAR const posix_spawn_file_actions_t *actions,
-                bool cloexec)
+                bool exec)
 {
   bool fcloexec;
   int ret;
@@ -765,7 +773,7 @@ int fdlist_copy(FAR struct fdlist *plist, FAR struct fdlist 
*clist,
               continue;
             }
 
-          fcloexec = cloexec && fdp->f_cloexec;
+          fcloexec = exec && fdp->f_cloexec;
 
           /* Skip file dup if file action is unnecessary to duplicate */
 
@@ -797,9 +805,13 @@ int fdlist_copy(FAR struct fdlist *plist, FAR struct 
fdlist *clist,
               return ret;
             }
 
-          /* Assign filep to the child's descriptor list. Omit the flags */
+          /* Assign filep to the child's descriptor list.  A fork() child
+           * keeps the close-on-exec flag of each descriptor (POSIX); the
+           * descriptors that a new program keeps have none.
+           */
 
-          fdlist_install(clist, fd, filep, fdp, 0, true);
+          fdlist_install(clist, fd, filep, fdp,
+                         !exec && fdp->f_cloexec ? O_CLOEXEC : 0, true);
           file_put(filep);
         }
     }
diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h
index bcd438ece95..8f74c119988 100644
--- a/include/nuttx/fs/fs.h
+++ b/include/nuttx/fs/fs.h
@@ -959,7 +959,7 @@ int fdlist_count(FAR struct fdlist *list);
 
 int fdlist_copy(FAR struct fdlist *plist, FAR struct fdlist *clist,
                 FAR const posix_spawn_file_actions_t *actions,
-                bool cloexec);
+                bool exec);
 
 /****************************************************************************
  * Name: fdlist_get2
diff --git a/sched/group/group.h b/sched/group/group.h
index 4a639edc59f..7465f028a30 100644
--- a/sched/group/group.h
+++ b/sched/group/group.h
@@ -118,6 +118,6 @@ bool group_has_child(FAR struct task_group_s *group, pid_t 
pid);
 int  group_setupidlefiles(void);
 int  group_setuptaskfiles(FAR struct tcb_s *tcb,
                           FAR const posix_spawn_file_actions_t *actions,
-                          bool cloexec);
+                          bool exec);
 
 #endif /* __SCHED_GROUP_GROUP_H */
diff --git a/sched/group/group_setuptaskfiles.c 
b/sched/group/group_setuptaskfiles.c
index 18f69f49365..148200246e3 100644
--- a/sched/group/group_setuptaskfiles.c
+++ b/sched/group/group_setuptaskfiles.c
@@ -49,7 +49,8 @@
  * Input Parameters:
  *   tcb     - tcb of the new task.
  *   actions - The spawn file actions
- *   cloexec - Perform O_CLOEXEC on setup task files
+ *   exec    - True when the task is a new program: leave out the
+ *             close-on-exec descriptors (see fdlist_copy())
  *
  * Returned Value:
  *   Zero (OK) is returned on success; A negated errno value is returned on
@@ -61,7 +62,7 @@
 
 int group_setuptaskfiles(FAR struct tcb_s *tcb,
                          FAR const posix_spawn_file_actions_t *actions,
-                         bool cloexec)
+                         bool exec)
 {
   FAR struct task_group_s *group = tcb->group;
   int ret = OK;
@@ -87,7 +88,7 @@ int group_setuptaskfiles(FAR struct tcb_s *tcb,
       (tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
     {
       ret = fdlist_copy(&rtcb->group->tg_fdlist,
-                        &group->tg_fdlist, actions, cloexec);
+                        &group->tg_fdlist, actions, exec);
     }
 
   if (ret >= 0 && actions != NULL &&

Reply via email to