diff --git a/fs/vfs/fs_dup.c b/fs/vfs/fs_dup.c index 2cb0650f04..69f6e3a520 100644 --- a/fs/vfs/fs_dup.c +++ b/fs/vfs/fs_dup.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "inode/inode.h" @@ -49,7 +50,7 @@ * ****************************************************************************/ -int file_dup(FAR struct file *filep, int minfd) +int file_dup(FAR struct file *filep, int minfd, bool cloexec) { struct file filep2; int fd2; @@ -66,6 +67,11 @@ int file_dup(FAR struct file *filep, int minfd) /* Then allocate a new file descriptor for the inode */ + if (cloexec) + { + filep2.f_oflags |= O_CLOEXEC; + } + fd2 = file_allocate(filep2.f_inode, filep2.f_oflags, filep2.f_pos, filep2.f_priv, minfd, false); if (fd2 < 0) @@ -102,7 +108,7 @@ int dup(int fd) /* Let file_dup() do the real work */ - ret = file_dup(filep, 0); + ret = file_dup(filep, 0, 0); if (ret < 0) { goto err; diff --git a/fs/vfs/fs_fcntl.c b/fs/vfs/fs_fcntl.c index a873915579..65dede0c94 100644 --- a/fs/vfs/fs_fcntl.c +++ b/fs/vfs/fs_fcntl.c @@ -71,7 +71,13 @@ static int file_vfcntl(FAR struct file *filep, int cmd, va_list ap) { /* Does not set the errno variable in the event of a failure */ - ret = file_dup(filep, va_arg(ap, int)); + ret = file_dup(filep, va_arg(ap, int), false); + } + break; + + case F_DUPFD_CLOEXEC: + { + ret = file_dup(filep, va_arg(ap, int), true); } break; diff --git a/include/fcntl.h b/include/fcntl.h index 1557c02fa4..907180be92 100644 --- a/include/fcntl.h +++ b/include/fcntl.h @@ -82,24 +82,25 @@ /* fcntl() commands */ -#define F_DUPFD 0 /* Duplicate a file descriptor */ -#define F_GETFD 1 /* Read the file descriptor flags */ -#define F_GETFL 2 /* Read the file status flags */ -#define F_GETLEASE 3 /* Indicates what type of lease is held on fd (linux) */ -#define F_GETLK 4 /* Check if we could place a lock */ -#define F_GETOWN 5 /* Get the pid receiving SIGIO and SIGURG signals for fd */ -#define F_GETSIG 6 /* Get the signal sent */ -#define F_NOTIFY 7 /* Provide notification when directory referred to by fd changes (linux)*/ -#define F_SETFD 8 /* Set the file descriptor flags to value */ -#define F_SETFL 9 /* Set the file status flags to the value */ -#define F_SETLEASE 10 /* Set or remove file lease (linux) */ -#define F_SETLK 11 /* Acquire or release a lock on range of bytes */ -#define F_SETLKW 12 /* Like F_SETLK, but wait for lock to become available */ -#define F_SETOWN 13 /* Set pid that will receive SIGIO and SIGURG signals for fd */ -#define F_SETSIG 14 /* Set the signal to be sent */ -#define F_GETPATH 15 /* Get the path of the file descriptor(BSD/macOS) */ -#define F_ADD_SEALS 16 /* Add the bit-mask argument arg to the set of seals of the inode */ -#define F_GET_SEALS 17 /* Get (as the function result) the current set of seals of the inode */ +#define F_DUPFD 0 /* Duplicate a file descriptor */ +#define F_GETFD 1 /* Read the file descriptor flags */ +#define F_GETFL 2 /* Read the file status flags */ +#define F_GETLEASE 3 /* Indicates what type of lease is held on fd (linux) */ +#define F_GETLK 4 /* Check if we could place a lock */ +#define F_GETOWN 5 /* Get the pid receiving SIGIO and SIGURG signals for fd */ +#define F_GETSIG 6 /* Get the signal sent */ +#define F_NOTIFY 7 /* Provide notification when directory referred to by fd changes (linux)*/ +#define F_SETFD 8 /* Set the file descriptor flags to value */ +#define F_SETFL 9 /* Set the file status flags to the value */ +#define F_SETLEASE 10 /* Set or remove file lease (linux) */ +#define F_SETLK 11 /* Acquire or release a lock on range of bytes */ +#define F_SETLKW 12 /* Like F_SETLK, but wait for lock to become available */ +#define F_SETOWN 13 /* Set pid that will receive SIGIO and SIGURG signals for fd */ +#define F_SETSIG 14 /* Set the signal to be sent */ +#define F_GETPATH 15 /* Get the path of the file descriptor(BSD/macOS) */ +#define F_ADD_SEALS 16 /* Add the bit-mask argument arg to the set of seals of the inode */ +#define F_GET_SEALS 17 /* Get (as the function result) the current set of seals of the inode */ +#define F_DUPFD_CLOEXEC 18 /* Duplicate file descriptor with close-on-exit set. */ /* For posix fcntl() and lockf() */ diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 51e01c1efc..4bd0357e67 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -814,7 +814,7 @@ int file_allocate(FAR struct inode *inode, int oflags, off_t pos, * ****************************************************************************/ -int file_dup(FAR struct file *filep, int minfd); +int file_dup(FAR struct file *filep, int minfd, bool cloexec); /**************************************************************************** * Name: file_dup2 diff --git a/include/sys/socket.h b/include/sys/socket.h index e81b5fa359..2226797ec4 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -108,22 +108,25 @@ * recognized by Linux, not all are supported by NuttX. */ -#define MSG_OOB 0x0001 /* Process out-of-band data. */ -#define MSG_PEEK 0x0002 /* Peek at incoming messages. */ -#define MSG_DONTROUTE 0x0004 /* Don't use local routing. */ -#define MSG_CTRUNC 0x0008 /* Control data lost before delivery. */ -#define MSG_PROXY 0x0010 /* Supply or ask second address. */ -#define MSG_TRUNC 0x0020 -#define MSG_DONTWAIT 0x0040 /* Enable nonblocking IO. */ -#define MSG_EOR 0x0080 /* End of record. */ -#define MSG_WAITALL 0x0100 /* Wait for a full request. */ -#define MSG_FIN 0x0200 -#define MSG_SYN 0x0400 -#define MSG_CONFIRM 0x0800 /* Confirm path validity. */ -#define MSG_RST 0x1000 -#define MSG_ERRQUEUE 0x2000 /* Fetch message from error queue. */ -#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE. */ -#define MSG_MORE 0x8000 /* Sender will send more. */ +#define MSG_OOB 0x000001 /* Process out-of-band data. */ +#define MSG_PEEK 0x000002 /* Peek at incoming messages. */ +#define MSG_DONTROUTE 0x000004 /* Don't use local routing. */ +#define MSG_CTRUNC 0x000008 /* Control data lost before delivery. */ +#define MSG_PROXY 0x000010 /* Supply or ask second address. */ +#define MSG_TRUNC 0x000020 +#define MSG_DONTWAIT 0x000040 /* Enable nonblocking IO. */ +#define MSG_EOR 0x000080 /* End of record. */ +#define MSG_WAITALL 0x000100 /* Wait for a full request. */ +#define MSG_FIN 0x000200 +#define MSG_SYN 0x000400 +#define MSG_CONFIRM 0x000800 /* Confirm path validity. */ +#define MSG_RST 0x001000 +#define MSG_ERRQUEUE 0x002000 /* Fetch message from error queue. */ +#define MSG_NOSIGNAL 0x004000 /* Do not generate SIGPIPE. */ +#define MSG_MORE 0x008000 /* Sender will send more. */ +#define MSG_CMSG_CLOEXEC 0x100000 /* Set close_on_exit for file + * descriptor received through SCM_RIGHTS. + */ /* Protocol levels supported by get/setsockopt(): */ diff --git a/net/local/local_recvmsg.c b/net/local/local_recvmsg.c index d2a1f7eb6b..a104ad6063 100644 --- a/net/local/local_recvmsg.c +++ b/net/local/local_recvmsg.c @@ -114,7 +114,7 @@ static int psock_fifo_read(FAR struct socket *psock, FAR void *buf, #ifdef CONFIG_NET_LOCAL_SCM static void local_recvctl(FAR struct local_conn_s *conn, - FAR struct msghdr *msg) + FAR struct msghdr *msg, int flags) { FAR struct local_conn_s *peer; struct cmsghdr *cmsg; @@ -157,7 +157,7 @@ static void local_recvctl(FAR struct local_conn_s *conn, peer->lc_cfpcount : count; for (i = 0; i < count; i++) { - fds[i] = file_dup(peer->lc_cfps[i], 0); + fds[i] = file_dup(peer->lc_cfps[i], 0, !!(flags & MSG_CMSG_CLOEXEC)); file_close(peer->lc_cfps[i]); kmm_free(peer->lc_cfps[i]); peer->lc_cfps[i] = NULL; @@ -496,7 +496,7 @@ ssize_t local_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, if (len >= 0 && msg->msg_control && msg->msg_controllen > sizeof(struct cmsghdr)) { - local_recvctl(psock->s_conn, msg); + local_recvctl(psock->s_conn, msg, flags); } #endif /* CONFIG_NET_LOCAL_SCM */