Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions distrib/sets/lists/debug/mi
Original file line number Diff line number Diff line change
Expand Up @@ -2037,6 +2037,7 @@
./usr/libdata/debug/usr/tests/lib/libc/gen/t_arc4random.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/gen/t_assert.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/gen/t_basedirname.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/gen/t_close_range.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/gen/t_closefrom.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/gen/t_cpuset.debug tests-lib-debug debug,atf,compattestfile
./usr/libdata/debug/usr/tests/lib/libc/gen/t_ctype.debug tests-lib-debug debug,atf,compattestfile
Expand Down
1 change: 1 addition & 0 deletions distrib/sets/lists/tests/mi
Original file line number Diff line number Diff line change
Expand Up @@ -3096,6 +3096,7 @@
./usr/tests/lib/libc/gen/t_arc4random tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/gen/t_assert tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/gen/t_basedirname tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/gen/t_close_range tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/gen/t_closefrom tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/gen/t_cpuset tests-lib-tests compattestfile,atf
./usr/tests/lib/libc/gen/t_ctype tests-lib-tests compattestfile,atf
Expand Down
1 change: 1 addition & 0 deletions include/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ int pipe2(int *, int);
#if defined(_NETBSD_SOURCE)
int acct(const char *);
int closefrom(int);
int close_range(unsigned int, unsigned int, int);
int des_cipher(const char *, char *, long, int);
int des_setkey(const char *);
void endusershell(void);
Expand Down
62 changes: 62 additions & 0 deletions lib/libc/gen/close_range.3
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.Dd July 19, 2025
.Dt CLOSE_RANGE 3
.Os
.Sh NAME
.Nm close_range
.Nd delete open file descriptors
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In unistd.h
.Ft int
.Fn close_range "u_int first" "u_int last" "int flags"
.Sh DESCRIPTION
The
.Fn close_range
function deletes all open file descriptors between
.Fa first
and
.Fa last
inclusive, clamped to the range of open file descriptors.
Any errors encountered while closing file descriptors are ignored.
Supported
.Fa flags :
.Bl -tag -width ".Dv CLOSE_RANGE_CLOEXEC"
.It Dv CLOSE_RANGE_CLOEXEC
Set the close-on-exec flag on descriptors in the range instead of closing them.
.It Dv CLOSE_RANGE_CLOFORK
Set the close-on-fork flag on descriptors in the range instead of closing them.
.El
.Sh RETURN VALUES
Upon successful completion,
.Fn close_range
returns a value
of 0.
Otherwise, a value of -1 is returned and the global variable
.Va errno
is set to indicate the error.
.Sh ERRORS
The
.Fn close_range
function
will fail if:
.Bl -tag -width Er
.It Bq Er EINVAL
The
.Fa last
argument is lower than the
.Fa first
argument.
.It Bq Er EINVAL
An invalid flag was set.
.El
.Sh SEE ALSO
.Xr close 2
.Xr closefrom 3
.Sh HISTORY
The
.Fn close_range
function comes from Linux and first appeared in
.Fx 8.0
and
.Nx 11.0 .
11 changes: 11 additions & 0 deletions lib/libc/gen/closefrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ __RCSID("$NetBSD: closefrom.c,v 1.4 2018/01/17 01:24:29 kamil Exp $");
#include <fcntl.h>
#include <unistd.h>

int
close_range(unsigned int first, unsigned int last, int flags)
{
struct fclose_range_args cr = {
.last = last,
.flags = flags
};

return (fcntl(first, F_CLOSE_RANGE, &cr));
}

int
closefrom(int fd)
{
Expand Down
26 changes: 26 additions & 0 deletions sys/kern/sys_descrip.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,13 +336,39 @@ sys_fcntl(struct lwp *l, const struct sys_fcntl_args *uap, register_t *retval)
struct flock fl;
bool cloexec = false;
bool clofork = false;
struct fclose_range_args cr;

fd = SCARG(uap, fd);
cmd = SCARG(uap, cmd);
fdp = l->l_fd;
error = 0;

switch (cmd) {
case F_CLOSE_RANGE:
if (fd < 0)
return EINVAL;
error = copyin(SCARG(uap, arg), &cr, sizeof(cr));
if (error)
return error;
if (cr.flags & ~(CLOSE_RANGE_CLOEXEC|CLOSE_RANGE_CLOFORK))
return EINVAL;
if ((unsigned int)fd > cr.last)
return EINVAL;
cr.last = MIN(cr.last, fdp->fd_lastfile);
for (i = fd; i <= (int)cr.last; i++) {
fp = fd_getfile(i);
if (fp == NULL)
continue;
if (cr.flags != 0) {
fd_set_exclose(l, i,
(cr.flags & CLOSE_RANGE_CLOEXEC) != 0);
fd_set_foclose(l, i,
(cr.flags & CLOSE_RANGE_CLOFORK) != 0);
fd_putfile(i);
} else
fd_close(i);
}
return 0;
case F_CLOSEM:
if (fd < 0)
return EBADF;
Expand Down
8 changes: 8 additions & 0 deletions sys/sys/fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,14 @@
#define F_DUPFD_CLOBOTH 19 /* close on exec/fork duplicated fd */
#endif

#if defined(_NETBSD_SOURCE)
#define F_CLOSE_RANGE 20 /* close_range(3) */
struct fclose_range_args {
unsigned int last; /* last file descriptor */
int flags; /* CLOSE_RANGE_* flags */
};
#endif

/* file descriptor flags (F_GETFD, F_SETFD) */
#define FD_CLOEXEC 1 /* close-on-exec flag */
#define FD_CLOFORK 2 /* close-on-fork flag */
Expand Down
6 changes: 6 additions & 0 deletions sys/sys/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,4 +344,10 @@
/* configurable system strings */
#define _CS_PATH 1

#ifdef _NETBSD_SOURCE
/* close_range(3) flags */
#define CLOSE_RANGE_CLOEXEC (1<<2)
#define CLOSE_RANGE_CLOFORK (1<<3)
#endif

#endif /* !_SYS_UNISTD_H_ */
1 change: 1 addition & 0 deletions tests/lib/libc/gen/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ TESTS_C+= t_arc4random
TESTS_C+= t_assert
TESTS_C+= t_basedirname
TESTS_C+= t_closefrom
TESTS_C+= t_close_range
TESTS_C+= t_cpuset
TESTS_C+= t_ctype
TESTS_C+= t_dir
Expand Down
Loading