Page MenuHomeFreeBSD

D21627.id62044.diff
No OneTemporary

D21627.id62044.diff

Index: include/unistd.h
===================================================================
--- include/unistd.h
+++ include/unistd.h
@@ -326,6 +326,9 @@
int chdir(const char *);
int chown(const char *, uid_t, gid_t);
int close(int);
+#if __BSD_VISIBLE
+int close_range(unsigned int, unsigned int, int);
+#endif
void closefrom(int);
int dup(int);
int dup2(int, int);
Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -375,6 +375,7 @@
chown.2 lchown.2
MLINKS+=clock_gettime.2 clock_getres.2 \
clock_gettime.2 clock_settime.2
+MLINKS+=closefrom.2 close_range.2
MLINKS+=nanosleep.2 clock_nanosleep.2
MLINKS+=cpuset.2 cpuset_getid.2 \
cpuset.2 cpuset_setid.2
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -403,6 +403,7 @@
FBSD_1.6 {
__sysctlbyname;
+ close_range;
copy_file_range;
fhlink;
fhlinkat;
Index: lib/libc/sys/closefrom.2
===================================================================
--- lib/libc/sys/closefrom.2
+++ lib/libc/sys/closefrom.2
@@ -29,7 +29,8 @@
.Dt CLOSEFROM 2
.Os
.Sh NAME
-.Nm closefrom
+.Nm closefrom ,
+.Nm close_range
.Nd delete open file descriptors
.Sh LIBRARY
.Lb libc
@@ -37,6 +38,8 @@
.In unistd.h
.Ft void
.Fn closefrom "int lowfd"
+.Ft int
+.Fn close_range "u_int lowfd" "u_int highfd" "int flags"
.Sh DESCRIPTION
The
.Fn closefrom
@@ -44,6 +47,40 @@
.Fa lowfd
from the per-process object reference table.
Any errors encountered while closing file descriptors are ignored.
+.Pp
+The
+.Fn close_range
+system call deletes all open file descriptors between
+.Fa lowfd
+and
+.Fa highfd
+inclusive, clamped to the range of open file descriptors.
+Any errors encountered while closing file descriptors are ignored.
+There are currently no defined
+.Fa flags .
+.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
+system call
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa highfd
+argument is lower than the
+.Fa lowfd
+argument.
+.It Bq Er EINVAL
+An invalid flag was set.
+.El
.Sh SEE ALSO
.Xr close 2
.Sh HISTORY
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1153,5 +1153,7 @@
570 AUE_SYSCTL STD { int freebsd32___sysctlbyname(const char *name, \
size_t namelen, void *old, uint32_t *oldlenp, \
void *new, size_t newlen); }
+571 AUE_NULL NOPROTO { int close_range(u_int lowfd, u_int highfd, \
+ int flags); }
; vim: syntax=off
Index: sys/kern/capabilities.conf
===================================================================
--- sys/kern/capabilities.conf
+++ sys/kern/capabilities.conf
@@ -126,6 +126,7 @@
## Always allow file descriptor close(2).
##
close
+close_range
closefrom
##
Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c
+++ sys/kern/kern_descrip.c
@@ -1256,6 +1256,57 @@
return (closefp(fdp, fd, fp, td, 1));
}
+int
+kern_close_range(struct thread *td, u_int lowfd, u_int highfd)
+{
+ struct filedesc *fdp;
+ int fd, ret;
+
+ ret = 0;
+ fdp = td->td_proc->p_fd;
+ FILEDESC_SLOCK(fdp);
+
+ /* Clamped to [lowfd, fd_lastfile] */
+ highfd = MIN(highfd, fdp->fd_lastfile);
+ if (highfd < lowfd) {
+ ret = EINVAL;
+ goto out;
+ }
+ for (fd = lowfd; fd <= highfd; fd++) {
+ if (fdp->fd_ofiles[fd].fde_file != NULL) {
+ FILEDESC_SUNLOCK(fdp);
+ (void)kern_close(td, fd);
+ FILEDESC_SLOCK(fdp);
+ }
+ }
+out:
+ FILEDESC_SUNLOCK(fdp);
+ return (ret);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct close_range_args {
+ u_int lowfd;
+ u_int highfd;
+ int flags;
+};
+#endif
+int
+sys_close_range(struct thread *td, struct close_range_args *uap)
+{
+
+ /* No flags currently defined */
+ if (uap->flags != 0)
+ return (EINVAL);
+ /*
+ * We won't sanity check lowfd < highfd here because highfd may be
+ * clamped down to the highest fd opened, which could be lower than
+ * lowfd while highfd wouldn't be. Let the implementation validate
+ * the range of fd and return an error as necessary.
+ */
+ return (kern_close_range(td, uap->lowfd, uap->highfd));
+}
+
/*
* Close open file descriptors.
*/
@@ -1268,28 +1319,16 @@
int
sys_closefrom(struct thread *td, struct closefrom_args *uap)
{
- struct filedesc *fdp;
- int fd;
+ u_int lowfd;
- fdp = td->td_proc->p_fd;
AUDIT_ARG_FD(uap->lowfd);
/*
* Treat negative starting file descriptor values identical to
* closefrom(0) which closes all files.
*/
- if (uap->lowfd < 0)
- uap->lowfd = 0;
- FILEDESC_SLOCK(fdp);
- for (fd = uap->lowfd; fd <= fdp->fd_lastfile; fd++) {
- if (fdp->fd_ofiles[fd].fde_file != NULL) {
- FILEDESC_SUNLOCK(fdp);
- (void)kern_close(td, fd);
- FILEDESC_SLOCK(fdp);
- }
- }
- FILEDESC_SUNLOCK(fdp);
- return (0);
+ lowfd = MAX(0, uap->lowfd);
+ return (kern_close_range(td, lowfd, ~0U));
}
#if defined(COMPAT_43)
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -3194,6 +3194,13 @@
_In_reads_bytes_opt_(newlen) void *new,
size_t newlen);
}
+571 AUE_NULL STD {
+ int close_range(
+ u_int lowfd,
+ u_int highfd,
+ int flags
+ );
+ }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h
+++ sys/sys/syscallsubr.h
@@ -91,6 +91,7 @@
const struct timespec *rqtp, struct timespec *rmtp);
int kern_clock_settime(struct thread *td, clockid_t clock_id,
struct timespec *ats);
+int kern_close_range(struct thread *td, u_int lowfd, u_int highfd);
int kern_close(struct thread *td, int fd);
int kern_connectat(struct thread *td, int dirfd, int fd,
struct sockaddr *sa);
Index: tests/sys/file/closefrom_test.c
===================================================================
--- tests/sys/file/closefrom_test.c
+++ tests/sys/file/closefrom_test.c
@@ -146,7 +146,7 @@
pid_t pid;
int fd, i, start;
- printf("1..15\n");
+ printf("1..19\n");
/* We better start up with fd's 0, 1, and 2 open. */
start = devnull();
@@ -271,5 +271,43 @@
fail("closefrom", "highest fd %d", fd);
ok("closefrom");
+ /* Chew up another 8 fd */
+ for (i = 0; i < 8; i++)
+ (void)devnull();
+ fd = highest_fd();
+ start = fd - 7;
+
+ /* close_range() a hole in the middle */
+ close_range(start + 3, start + 5, 0);
+ for (i = start + 3; i < start + 6; ++i) {
+ if (close(i) == 0 || errno != EBADF) {
+ --i;
+ break;
+ }
+ }
+ if (i != start + 6)
+ fail("close_range", "failed to close at %d in %d - %d", i + 1,
+ start + 3, start + 6);
+ ok("close_range");
+
+ /* close_range from the middle of the hole */
+ close_range(start + 4, start + 6, 0);
+ if ((i = highest_fd()) != fd)
+ fail("close_range", "highest fd %d", i);
+ ok("close_range");
+
+ /* close_range to the end; effectively closefrom(2) */
+ close_range(start + 3, ~0L, 0);
+ if ((i = highest_fd()) != start + 2)
+ fail("close_range", "highest fd %d", i);
+ ok("close_range");
+
+ /* Now close the rest */
+ close_range(start, start + 4, 0);
+ fd = highest_fd();
+ if (fd != 3)
+ fail("close_range", "highest fd %d", fd);
+ ok("close_range");
+
return (0);
}

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 10, 1:53 AM (12 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29468694
Default Alt Text
D21627.id62044.diff (7 KB)

Event Timeline