Re: [PATCH] Add posix_spawn_file_actions_addclosefrom_np
Chris Hanson <[email protected]> Tue, 21 Apr 2026 14:33:24 -0700
| Newsgroups | gmane.os.netbsd.devel.kernel |
|---|---|
| Message-ID | <[email protected]> |
Attached a patch with corrected commit message. Thanks to [email protected] <mailto:[email protected]> for the catch! -- Chris -- who wishes he could submit a PR... maybe someday
0001-Add-posix_spawn_file_actions_addclosefrom_np.patch
(application/octet-stream, 8.9 KB)
From 0f8e1df8d173bba6a759fc5147dd3e61634257ed Mon Sep 17 00:00:00 2001 From: Chris Hanson <[email protected]> Date: Sat, 18 Apr 2026 16:30:18 -0700 Subject: [PATCH] Add posix_spawn_file_actions_addclosefrom_np Add support for a closefrom(3) action to posix_spawn_file_actions_t. This can be used to ensure all but specific low-numbered descriptors are closed in the child process. Rationale: In a large or complex application or one using many libraries, the caller of posix_spawn(3) can't necessarily have complete knowledge of the state of all descriptors that could potentially be inherited by the child process. --- include/spawn.h | 2 ++ lib/libc/gen/posix_spawn.3 | 1 + .../gen/posix_spawn_file_actions_addopen.3 | 25 ++++++++++++++++--- lib/libc/gen/posix_spawn_file_actions_init.3 | 1 + lib/libc/gen/posix_spawn_fileactions.c | 21 ++++++++++++++++ sys/kern/kern_exec.c | 12 ++++++++- sys/sys/spawn.h | 10 +++++++- .../lib/libc/gen/posix_spawn/h_fileactions.c | 11 ++++++++ .../lib/libc/gen/posix_spawn/t_fileactions.c | 25 ++++++++++++++++++- 9 files changed, 102 insertions(+), 6 deletions(-) diff --git a/include/spawn.h b/include/spawn.h index 32cdd85ca27f..846cb15cc694 100644 --- a/include/spawn.h +++ b/include/spawn.h @@ -60,6 +60,8 @@ int posix_spawn_file_actions_addchdir(posix_spawn_file_actions_t * __restrict, const char * __restrict); int posix_spawn_file_actions_addfchdir(posix_spawn_file_actions_t *, int); +int posix_spawn_file_actions_addclosefrom_np(posix_spawn_file_actions_t *, int); + /* * Spawn attributes */ diff --git a/lib/libc/gen/posix_spawn.3 b/lib/libc/gen/posix_spawn.3 index 6ca4a59a0810..379da1708fd6 100644 --- a/lib/libc/gen/posix_spawn.3 +++ b/lib/libc/gen/posix_spawn.3 @@ -444,6 +444,7 @@ is returned. .Xr vfork 2 , .Xr posix_spawn_file_actions_addchdir 3 , .Xr posix_spawn_file_actions_addclose 3 , +.Xr posix_spawn_file_actions_addclosefrom_np 3 , .Xr posix_spawn_file_actions_adddup2 3 , .Xr posix_spawn_file_actions_addfchdir 3 , .Xr posix_spawn_file_actions_addopen 3 , diff --git a/lib/libc/gen/posix_spawn_file_actions_addopen.3 b/lib/libc/gen/posix_spawn_file_actions_addopen.3 index 9a23d6f9e899..82f2bf9b7c0d 100644 --- a/lib/libc/gen/posix_spawn_file_actions_addopen.3 +++ b/lib/libc/gen/posix_spawn_file_actions_addopen.3 @@ -42,8 +42,9 @@ .Sh NAME .Nm posix_spawn_file_actions_addopen , .Nm posix_spawn_file_actions_adddup2 , -.Nm posix_spawn_file_actions_addclose -.Nd "add open, dup2 or close action to spawn file actions object" +.Nm posix_spawn_file_actions_addclose , +.Nm posix_spawn_file_actions_addclosefrom_np +.Nd "add open, dup2, close, or closefrom action to spawn file actions object" .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -54,8 +55,10 @@ .Fn posix_spawn_file_actions_adddup2 "posix_spawn_file_actions_t * file_actions" "int fildes" "int newfildes" .Ft int .Fn posix_spawn_file_actions_addclose "posix_spawn_file_actions_t * file_actions" "int fildes" +.Ft int +.Fn posix_spawn_file_actions_addclosefrom_np "posix_spawn_file_actions_t * file_actions" "int fildes" .Sh DESCRIPTION -These functions add an open, dup2 or close action to a spawn +These functions add an open, dup2, close, or closefrom action to a spawn file actions object. .Pp A spawn file actions object is of type @@ -140,6 +143,21 @@ close(fildes) .Pp had been called) when a new process is spawned using this file actions object. +.Pp +The +.Fn posix_spawn_file_actions_addclosefrom_np +function, a non-POSIX extension, adds a closefrom action to the object +referenced by +.Fa file_actions +that causes the file descriptor +.Fa filedes +and all higher file descriptors to be closed (as if +.Bd -literal -offset indent +closefrom(filedes) +.Ed +.Pp +had been called) when a new process is spawned using this file actions +object. .Sh RETURN VALUES Upon successful completion, these functions return zero; otherwise, an error number is returned to indicate the error. @@ -164,6 +182,7 @@ Insufficient memory exists to add to the spawn file actions object. .Xr close 2 , .Xr dup2 2 , .Xr open 2 , +.Xr closefrom 3 , .Xr posix_spawn 3 , .Xr posix_spawn_file_actions_destroy 3 , .Xr posix_spawn_file_actions_init 3 , diff --git a/lib/libc/gen/posix_spawn_file_actions_init.3 b/lib/libc/gen/posix_spawn_file_actions_init.3 index d33a09c267b3..366a68d45d16 100644 --- a/lib/libc/gen/posix_spawn_file_actions_init.3 +++ b/lib/libc/gen/posix_spawn_file_actions_init.3 @@ -89,6 +89,7 @@ Insufficient memory exists to initialize the spawn file actions object. .Sh SEE ALSO .Xr posix_spawn 3 , .Xr posix_spawn_file_actions_addclose 3 , +.Xr posix_spawn_file_actions_addclosefrom_np 3 , .Xr posix_spawn_file_actions_adddup2 3 , .Xr posix_spawn_file_actions_addopen 3 , .Xr posix_spawnp 3 diff --git a/lib/libc/gen/posix_spawn_fileactions.c b/lib/libc/gen/posix_spawn_fileactions.c index 1ff45c97faa5..7ac4170420fc 100644 --- a/lib/libc/gen/posix_spawn_fileactions.c +++ b/lib/libc/gen/posix_spawn_fileactions.c @@ -215,3 +215,24 @@ posix_spawn_file_actions_addfchdir(posix_spawn_file_actions_t *fa, int fildes) return 0; } + +int +posix_spawn_file_actions_addclosefrom_np(posix_spawn_file_actions_t *fa, + int fildes) +{ + unsigned int i; + int error; + + if (fildes < 0) + return EBADF; + + error = posix_spawn_file_actions_getentry(fa, &i); + if (error) + return error; + + fa->fae[i].fae_action = FAE_CLOSEFROM; + fa->fae[i].fae_fildes = fildes; + fa->len++; + + return 0; +} diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 0d1b498ab303..ccce65d88e57 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -2154,7 +2154,7 @@ handle_posix_spawn_file_actions(struct posix_spawn_file_actions *actions) { struct lwp *l = curlwp; register_t retval; - int error = 0, newfd; + int error = 0, newfd, fd; if (actions == NULL) return 0; @@ -2201,6 +2201,16 @@ handle_posix_spawn_file_actions(struct posix_spawn_file_actions *actions) case FAE_FCHDIR: error = do_sys_fchdir(l, fae->fae_fildes, &retval); break; + case FAE_CLOSEFROM: + /* + * as above, ignore failures from close(). + */ + while ((fd = l->l_fd->fd_lastfile) >= fae->fae_fildes) { + if (fd_getfile(fd) != NULL) { + fd_close(fd); + } + } + break; } if (error) return error; diff --git a/sys/sys/spawn.h b/sys/sys/spawn.h index b04db01bd03c..ecca5c9ad541 100644 --- a/sys/sys/spawn.h +++ b/sys/sys/spawn.h @@ -47,7 +47,15 @@ struct posix_spawnattr { sigset_t sa_sigmask; }; -enum fae_action { FAE_OPEN, FAE_DUP2, FAE_CLOSE, FAE_CHDIR, FAE_FCHDIR }; +enum fae_action { + FAE_OPEN, + FAE_DUP2, + FAE_CLOSE, + FAE_CHDIR, + FAE_FCHDIR, + FAE_CLOSEFROM, +}; + typedef struct posix_spawn_file_actions_entry { enum fae_action fae_action; diff --git a/tests/lib/libc/gen/posix_spawn/h_fileactions.c b/tests/lib/libc/gen/posix_spawn/h_fileactions.c index c658600bbf1c..0d9637b7d1ec 100644 --- a/tests/lib/libc/gen/posix_spawn/h_fileactions.c +++ b/tests/lib/libc/gen/posix_spawn/h_fileactions.c @@ -100,6 +100,17 @@ main(int argc, char **argv) fprintf(stderr, "%s: stat results differ\n", getprogname()); res = EXIT_FAILURE; } + /* file descs 8 and 9 should be closed (via addclosefrom_np) */ + if (read(8, buf, BUFSIZE) != -1 || errno != EBADF) { + fprintf(stderr, "%s: filedesc 8 is not closed\n", + getprogname()); + res = EXIT_FAILURE; + } + if (read(9, buf, BUFSIZE) != -1 || errno != EBADF) { + fprintf(stderr, "%s: filedesc 9 is not closed\n", + getprogname()); + res = EXIT_FAILURE; + } return res; } diff --git a/tests/lib/libc/gen/posix_spawn/t_fileactions.c b/tests/lib/libc/gen/posix_spawn/t_fileactions.c index 57e27a0ada46..d500903a685d 100644 --- a/tests/lib/libc/gen/posix_spawn/t_fileactions.c +++ b/tests/lib/libc/gen/posix_spawn/t_fileactions.c @@ -274,7 +274,7 @@ ATF_TC_HEAD(t_spawn_fileactions, tc) } ATF_TC_BODY(t_spawn_fileactions, tc) { - int fd1, fd2, fd3, status; + int fd1, fd2, fd3, fd4, fd5, fd6, fd7, status; pid_t pid; char * const args[2] = { __UNCONST("h_fileactions"), NULL }; char helper[FILENAME_MAX]; @@ -297,6 +297,29 @@ ATF_TC_BODY(t_spawn_fileactions, tc) RZ(posix_spawn_file_actions_addopen(&fa, 6, "/dev/null", O_RDWR, 0)); RZ(posix_spawn_file_actions_adddup2(&fa, 1, 7)); + /* + * Open descriptors 6 & 7 so we can get to 8 & 9 for testing + * closefrom_np, but close 6 & 7 before the spawn since the + * child process will get them via the open and dup2 actions + * above. + */ + RL(fd4 = open("/dev/null", O_RDONLY)); + ATF_REQUIRE(fd4 = 6); + + RL(fd5 = open("/dev/null", O_RDONLY)); + ATF_REQUIRE(fd5 = 7); + + RL(fd6 = open("/dev/null", O_RDONLY)); + ATF_REQUIRE(fd6 = 8); + + RL(fd7 = open("/dev/null", O_RDONLY)); + ATF_REQUIRE(fd7 = 9); + + close(fd4); + close(fd5); + + RZ(posix_spawn_file_actions_addclosefrom_np(&fa, 8)); + snprintf(helper, sizeof helper, "%s/h_fileactions", atf_tc_get_config_var(tc, "srcdir")); RZ(posix_spawn(&pid, helper, &fa, NULL, args, NULL)); -- 2.53.0