sched/task: close file descriptor with O_CLOEXEC before active task or exec

VELAPLATFO-18473

refs:
https://man7.org/linux/man-pages/man2/fcntl.2.html
If the FD_CLOEXEC bit is set, the file descriptor will automatically
be closed during a successful execve(2).
(If the execve(2) fails, the file descriptor is left open.)

modify:
1. Ensure that the child task copies all fds of the parent task,
   including those with O_CLOEXE.
2. Make sure spawn_file_action is executed under fd with O_CLOEXEC,
   otherwise it will fail.
3. When a new task is activated or exec is called, close all fds
   with O_CLOEXEC flags.

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1 2023-10-22 17:06:46 +08:00 committed by Xiang Xiao
parent 73dc8f84cc
commit 18819b6b24
5 changed files with 67 additions and 4 deletions

View File

@ -34,6 +34,7 @@
#include <nuttx/addrenv.h>
#include <nuttx/arch.h>
#include <nuttx/fs/fs.h>
#include <nuttx/kmalloc.h>
#include <nuttx/sched.h>
#include <sched/sched.h>
@ -375,6 +376,10 @@ int exec_module(FAR struct binary_s *binp,
}
#endif
/* Close the file descriptors with O_CLOEXEC before active task */
files_close_onexec(&tcb->cmn);
if (!spawn)
{
exec_swap(this_task(), (FAR struct tcb_s *)tcb);

View File

@ -462,8 +462,7 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
filep = &plist->fl_files[i][j];
if (filep && (filep->f_inode == NULL ||
(filep->f_oflags & O_CLOEXEC) != 0))
if (filep && filep->f_inode == NULL)
{
continue;
}
@ -474,9 +473,10 @@ int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist)
goto out;
}
/* Yes... duplicate it for the child */
/* Yes... duplicate it for the child, include O_CLOEXEC flag. */
ret = file_dup2(filep, &clist->fl_files[i][j]);
ret = file_dup3(filep, &clist->fl_files[i][j],
filep->f_oflags & O_CLOEXEC ? O_CLOEXEC : 0);
if (ret < 0)
{
goto out;
@ -489,6 +489,44 @@ out:
return ret;
}
/****************************************************************************
* Name: files_close_onexec
*
* Description:
* Close specified task's file descriptors with O_CLOEXEC before exec.
*
****************************************************************************/
void files_close_onexec(FAR struct tcb_s *tcb)
{
FAR struct filelist *list;
int i;
int j;
/* Get the file descriptor list. It should not be NULL in this context. */
list = nxsched_get_files_from_tcb(tcb);
DEBUGASSERT(list != NULL);
nxmutex_lock(&list->fl_lock);
for (i = 0; i < list->fl_rows; i++)
{
for (j = 0; j < CONFIG_NFILE_DESCRIPTORS_PER_BLOCK; j++)
{
FAR struct file *filep;
filep = &list->fl_files[i][j];
if (filep && filep->f_inode != NULL &&
(filep->f_oflags & O_CLOEXEC) != 0)
{
file_close(filep);
}
}
}
nxmutex_unlock(&list->fl_lock);
}
/****************************************************************************
* Name: fs_getfilep
*

View File

@ -865,6 +865,16 @@ void files_releaselist(FAR struct filelist *list);
int files_duplist(FAR struct filelist *plist, FAR struct filelist *clist);
/****************************************************************************
* Name: files_close_onexec
*
* Description:
* Close specified task's file descriptors with O_CLOEXEC before exec.
*
****************************************************************************/
void files_close_onexec(FAR struct tcb_s *tcb);
/****************************************************************************
* Name: file_allocate_from_tcb
*

View File

@ -33,6 +33,7 @@
#include <nuttx/kmalloc.h>
#include <nuttx/sched.h>
#include <nuttx/kthread.h>
#include <nuttx/fs/fs.h>
#include "sched/sched.h"
#include "group/group.h"
@ -102,6 +103,10 @@ int nxthread_create(FAR const char *name, uint8_t ttype, int priority,
return ret;
}
/* Close the file descriptors with O_CLOEXEC before active task */
files_close_onexec(&tcb->cmn);
/* Get the assigned pid before we start the task */
pid = tcb->cmn.pid;

View File

@ -31,6 +31,7 @@
#include <debug.h>
#include <errno.h>
#include <nuttx/fs/fs.h>
#include <nuttx/sched.h>
#include <nuttx/kthread.h>
#include <nuttx/spawn.h>
@ -125,6 +126,10 @@ static int nxtask_spawn_create(FAR const char *name, int priority,
}
}
/* Close the file descriptors with O_CLOEXEC before active task */
files_close_onexec(&tcb->cmn);
/* Set the attributes */
if (attr)