From owner-svn-src-stable-12@freebsd.org Wed Aug 5 03:54:02 2020 Return-Path: Delivered-To: svn-src-stable-12@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 805DE3A9524; Wed, 5 Aug 2020 03:54:02 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BLyRG39N1z4GLg; Wed, 5 Aug 2020 03:54:02 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4FF58104E9; Wed, 5 Aug 2020 03:54:02 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0753s2X9006358; Wed, 5 Aug 2020 03:54:02 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0753rv6L006334; Wed, 5 Aug 2020 03:53:57 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <202008050353.0753rv6L006334@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Wed, 5 Aug 2020 03:53:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r363879 - in stable/12: include lib/libc/sys sys/compat/freebsd32 sys/kern sys/sys tests/sys/file X-SVN-Group: stable-12 X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: in stable/12: include lib/libc/sys sys/compat/freebsd32 sys/kern sys/sys tests/sys/file X-SVN-Commit-Revision: 363879 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-12@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for only the 12-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Aug 2020 03:54:02 -0000 Author: kevans Date: Wed Aug 5 03:53:57 2020 New Revision: 363879 URL: https://svnweb.freebsd.org/changeset/base/363879 Log: MFC r359836-r359837, r359891, r360236-r360237: close_range(2) This commit diverges from our usual procedure of committing generated files separately because the original commit, r359836, conflated userland use (in tests) with the implementation. __FreeBSD_version was already bumped ~15 hours prior to this MFC, 1201522 marks the introduction of close_range. CPython will use this syscall for some pretty sizable performance gains. r359836: Implement a close_range(2) syscall close_range(min, max, flags) allows for a range of descriptors to be closed. The Python folk have indicated that they would much prefer this interface to closefrom(2), as the case may be that they/someone have special fds dup'd to higher in the range and they can't necessarily closefrom(min) because they don't want to hit the upper range, but relocating them to lower isn't necessarily feasible. sys_closefrom has been rewritten to use kern_close_range() using ~0U to indicate closing to the end of the range. This was chosen rather than requiring callers of kern_close_range() to hold FILEDESC_SLOCK across the call to kern_close_range for simplicity. The flags argument of close_range(2) is currently unused, so any flags set is currently EINVAL. It was added to the interface in Linux so that future flags could be added for, e.g., "halt on first error" and things of this nature. This patch is based on a syscall of the same design that is expected to be merged into Linux. r359837: sysent: re-roll after introduction of close_range in r359836 r359891: close_range/closefrom: fix regression from close_range introduction close_range will clamp the range between [0, fdp->fd_lastfile], but failed to take into account that fdp->fd_lastfile can become -1 if all fds are closed. =-( In this scenario, just return because there's nothing further we can do at the moment. Add a test case for this, fork() and simply closefrom(0) twice in the child; on the second invocation, fdp->fd_lastfile == -1 and will trigger a panic before this change. r360236: close_range(2): use newly assigned AUE_CLOSERANGE r360237: sysent: re-roll after 360236 (AUE_CLOSERANGE used) Modified: stable/12/include/unistd.h stable/12/lib/libc/sys/Makefile.inc stable/12/lib/libc/sys/Symbol.map stable/12/lib/libc/sys/closefrom.2 stable/12/sys/compat/freebsd32/freebsd32_syscall.h stable/12/sys/compat/freebsd32/freebsd32_syscalls.c stable/12/sys/compat/freebsd32/freebsd32_sysent.c stable/12/sys/compat/freebsd32/freebsd32_systrace_args.c stable/12/sys/compat/freebsd32/syscalls.master stable/12/sys/kern/capabilities.conf stable/12/sys/kern/init_sysent.c stable/12/sys/kern/kern_descrip.c stable/12/sys/kern/syscalls.c stable/12/sys/kern/syscalls.master stable/12/sys/kern/systrace_args.c stable/12/sys/sys/syscall.h stable/12/sys/sys/syscall.mk stable/12/sys/sys/syscallsubr.h stable/12/sys/sys/sysproto.h stable/12/tests/sys/file/closefrom_test.c Directory Properties: stable/12/ (props changed) Modified: stable/12/include/unistd.h ============================================================================== --- stable/12/include/unistd.h Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/include/unistd.h Wed Aug 5 03:53:57 2020 (r363879) @@ -494,6 +494,7 @@ struct crypt_data { int acct(const char *); int async_daemon(void); int check_utility_compat(const char *); +int close_range(unsigned int, unsigned int, int); const char * crypt_get_format(void); char *crypt_r(const char *, const char *, struct crypt_data *); Modified: stable/12/lib/libc/sys/Makefile.inc ============================================================================== --- stable/12/lib/libc/sys/Makefile.inc Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/lib/libc/sys/Makefile.inc Wed Aug 5 03:53:57 2020 (r363879) @@ -372,6 +372,7 @@ MLINKS+=chown.2 fchown.2 \ 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 Modified: stable/12/lib/libc/sys/Symbol.map ============================================================================== --- stable/12/lib/libc/sys/Symbol.map Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/lib/libc/sys/Symbol.map Wed Aug 5 03:53:57 2020 (r363879) @@ -402,6 +402,7 @@ FBSD_1.5 { }; FBSD_1.6 { + close_range; fhlink; fhlinkat; fhreadlink; Modified: stable/12/lib/libc/sys/closefrom.2 ============================================================================== --- stable/12/lib/libc/sys/closefrom.2 Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/lib/libc/sys/closefrom.2 Wed Aug 5 03:53:57 2020 (r363879) @@ -25,11 +25,12 @@ .\" .\" $FreeBSD$ .\" -.Dd June 12, 2009 +.Dd April 12, 2020 .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 @@ system call deletes all open file descriptors greater .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 Modified: stable/12/sys/compat/freebsd32/freebsd32_syscall.h ============================================================================== --- stable/12/sys/compat/freebsd32/freebsd32_syscall.h Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/compat/freebsd32/freebsd32_syscall.h Wed Aug 5 03:53:57 2020 (r363879) @@ -495,4 +495,5 @@ #define FREEBSD32_SYS_fhlinkat 566 #define FREEBSD32_SYS_fhreadlink 567 #define FREEBSD32_SYS_freebsd32___sysctlbyname 570 -#define FREEBSD32_SYS_MAXSYSCALL 571 +#define FREEBSD32_SYS_close_range 575 +#define FREEBSD32_SYS_MAXSYSCALL 576 Modified: stable/12/sys/compat/freebsd32/freebsd32_syscalls.c ============================================================================== --- stable/12/sys/compat/freebsd32/freebsd32_syscalls.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/compat/freebsd32/freebsd32_syscalls.c Wed Aug 5 03:53:57 2020 (r363879) @@ -607,4 +607,9 @@ const char *freebsd32_syscallnames[] = { "#568", /* 568 = funlinkat */ "#569", /* 569 = copy_file_range */ "freebsd32___sysctlbyname", /* 570 = freebsd32___sysctlbyname */ + "#571", /* 571 = shm_open2 */ + "#572", /* 572 = shm_rename */ + "#573", /* 573 = sigfastblock */ + "#574", /* 574 = __realpathat */ + "close_range", /* 575 = close_range */ }; Modified: stable/12/sys/compat/freebsd32/freebsd32_sysent.c ============================================================================== --- stable/12/sys/compat/freebsd32/freebsd32_sysent.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/compat/freebsd32/freebsd32_sysent.c Wed Aug 5 03:53:57 2020 (r363879) @@ -654,4 +654,9 @@ struct sysent freebsd32_sysent[] = { { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 568 = funlinkat */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 569 = copy_file_range */ { AS(freebsd32___sysctlbyname_args), (sy_call_t *)freebsd32___sysctlbyname, AUE_SYSCTL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 570 = freebsd32___sysctlbyname */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 571 = shm_open2 */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 572 = shm_rename */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 573 = sigfastblock */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 574 = __realpathat */ + { AS(close_range_args), (sy_call_t *)sys_close_range, AUE_CLOSERANGE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 575 = close_range */ }; Modified: stable/12/sys/compat/freebsd32/freebsd32_systrace_args.c ============================================================================== --- stable/12/sys/compat/freebsd32/freebsd32_systrace_args.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/compat/freebsd32/freebsd32_systrace_args.c Wed Aug 5 03:53:57 2020 (r363879) @@ -3322,6 +3322,15 @@ systrace_args(int sysnum, void *params, uint64_t *uarg *n_args = 6; break; } + /* close_range */ + case 575: { + struct close_range_args *p = params; + uarg[0] = p->lowfd; /* u_int */ + uarg[1] = p->highfd; /* u_int */ + iarg[2] = p->flags; /* int */ + *n_args = 3; + break; + } default: *n_args = 0; break; @@ -8942,6 +8951,22 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *d break; }; break; + /* close_range */ + case 575: + switch(ndx) { + case 0: + p = "u_int"; + break; + case 1: + p = "u_int"; + break; + case 2: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10813,6 +10838,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char * break; /* freebsd32___sysctlbyname */ case 570: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* close_range */ + case 575: if (ndx == 0 || ndx == 1) p = "int"; break; Modified: stable/12/sys/compat/freebsd32/syscalls.master ============================================================================== --- stable/12/sys/compat/freebsd32/syscalls.master Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/compat/freebsd32/syscalls.master Wed Aug 5 03:53:57 2020 (r363879) @@ -1132,5 +1132,11 @@ 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 UNIMPL shm_open2 +572 AUE_NULL UNIMPL shm_rename +573 AUE_NULL UNIMPL sigfastblock +574 AUE_NULL UNIMPL __realpathat +575 AUE_CLOSERANGE NOPROTO { int close_range(u_int lowfd, u_int highfd, \ + int flags); } ; vim: syntax=off Modified: stable/12/sys/kern/capabilities.conf ============================================================================== --- stable/12/sys/kern/capabilities.conf Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/kern/capabilities.conf Wed Aug 5 03:53:57 2020 (r363879) @@ -131,6 +131,7 @@ clock_gettime ## Always allow file descriptor close(2). ## close +close_range closefrom ## Modified: stable/12/sys/kern/init_sysent.c ============================================================================== --- stable/12/sys/kern/init_sysent.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/kern/init_sysent.c Wed Aug 5 03:53:57 2020 (r363879) @@ -620,4 +620,9 @@ struct sysent sysent[] = { { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 568 = funlinkat */ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 569 = copy_file_range */ { AS(__sysctlbyname_args), (sy_call_t *)sys___sysctlbyname, AUE_SYSCTL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 570 = __sysctlbyname */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 571 = shm_open2 */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 572 = shm_rename */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 573 = sigfastblock */ + { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 574 = __realpathat */ + { AS(close_range_args), (sy_call_t *)sys_close_range, AUE_CLOSERANGE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 575 = close_range */ }; Modified: stable/12/sys/kern/kern_descrip.c ============================================================================== --- stable/12/sys/kern/kern_descrip.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/kern/kern_descrip.c Wed Aug 5 03:53:57 2020 (r363879) @@ -1263,6 +1263,65 @@ kern_close(struct thread *td, int fd) 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); + + /* + * Check this prior to clamping; closefrom(3) with only fd 0, 1, and 2 + * open should not be a usage error. From a close_range() perspective, + * close_range(3, ~0U, 0) in the same scenario should also likely not + * be a usage error as all fd above 3 are in-fact already closed. + */ + if (highfd < lowfd) { + ret = EINVAL; + goto out; + } + + /* + * If fdp->fd_lastfile == -1, we're dealing with either a fresh file + * table or one in which every fd has been closed. Just return + * successful; there's nothing left to do. + */ + if (fdp->fd_lastfile == -1) + goto out; + /* Clamped to [lowfd, fd_lastfile] */ + highfd = MIN(highfd, fdp->fd_lastfile); + 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); + return (kern_close_range(td, uap->lowfd, uap->highfd)); +} + /* * Close open file descriptors. */ @@ -1275,28 +1334,16 @@ struct closefrom_args { 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) Modified: stable/12/sys/kern/syscalls.c ============================================================================== --- stable/12/sys/kern/syscalls.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/kern/syscalls.c Wed Aug 5 03:53:57 2020 (r363879) @@ -577,4 +577,9 @@ const char *syscallnames[] = { "#568", /* 568 = funlinkat */ "#569", /* 569 = copy_file_range */ "__sysctlbyname", /* 570 = __sysctlbyname */ + "#571", /* 571 = shm_open2 */ + "#572", /* 572 = shm_rename */ + "#573", /* 573 = sigfastblock */ + "#574", /* 574 = __realpathat */ + "close_range", /* 575 = close_range */ }; Modified: stable/12/sys/kern/syscalls.master ============================================================================== --- stable/12/sys/kern/syscalls.master Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/kern/syscalls.master Wed Aug 5 03:53:57 2020 (r363879) @@ -1380,6 +1380,17 @@ size_t newlen \ ); \ } +571 AUE_NULL UNIMPL shm_open2 +572 AUE_NULL UNIMPL shm_rename +573 AUE_NULL UNIMPL sigfastblock +574 AUE_NULL UNIMPL __realpathat +575 AUE_CLOSERANGE STD { \ + int close_range( \ + u_int lowfd, \ + u_int highfd, \ + int flags \ + ); \ + } ; Please copy any additions and changes to the following compatability tables: Modified: stable/12/sys/kern/systrace_args.c ============================================================================== --- stable/12/sys/kern/systrace_args.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/kern/systrace_args.c Wed Aug 5 03:53:57 2020 (r363879) @@ -3314,6 +3314,15 @@ systrace_args(int sysnum, void *params, uint64_t *uarg *n_args = 6; break; } + /* close_range */ + case 575: { + struct close_range_args *p = params; + uarg[0] = p->lowfd; /* u_int */ + uarg[1] = p->highfd; /* u_int */ + iarg[2] = p->flags; /* int */ + *n_args = 3; + break; + } default: *n_args = 0; break; @@ -8847,6 +8856,22 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *d break; }; break; + /* close_range */ + case 575: + switch(ndx) { + case 0: + p = "u_int"; + break; + case 1: + p = "u_int"; + break; + case 2: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -10745,6 +10770,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char * break; /* __sysctlbyname */ case 570: + if (ndx == 0 || ndx == 1) + p = "int"; + break; + /* close_range */ + case 575: if (ndx == 0 || ndx == 1) p = "int"; break; Modified: stable/12/sys/sys/syscall.h ============================================================================== --- stable/12/sys/sys/syscall.h Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/sys/syscall.h Wed Aug 5 03:53:57 2020 (r363879) @@ -504,4 +504,5 @@ #define SYS_fhlinkat 566 #define SYS_fhreadlink 567 #define SYS___sysctlbyname 570 -#define SYS_MAXSYSCALL 571 +#define SYS_close_range 575 +#define SYS_MAXSYSCALL 576 Modified: stable/12/sys/sys/syscall.mk ============================================================================== --- stable/12/sys/sys/syscall.mk Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/sys/syscall.mk Wed Aug 5 03:53:57 2020 (r363879) @@ -409,4 +409,5 @@ MIASM = \ fhlink.o \ fhlinkat.o \ fhreadlink.o \ - __sysctlbyname.o + __sysctlbyname.o \ + close_range.o Modified: stable/12/sys/sys/syscallsubr.h ============================================================================== --- stable/12/sys/sys/syscallsubr.h Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/sys/syscallsubr.h Wed Aug 5 03:53:57 2020 (r363879) @@ -93,6 +93,7 @@ int kern_clock_nanosleep(struct thread *td, clockid_t 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); Modified: stable/12/sys/sys/sysproto.h ============================================================================== --- stable/12/sys/sys/sysproto.h Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/sys/sys/sysproto.h Wed Aug 5 03:53:57 2020 (r363879) @@ -1798,6 +1798,11 @@ struct __sysctlbyname_args { char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)]; char newlen_l_[PADL_(size_t)]; size_t newlen; char newlen_r_[PADR_(size_t)]; }; +struct close_range_args { + char lowfd_l_[PADL_(u_int)]; u_int lowfd; char lowfd_r_[PADR_(u_int)]; + char highfd_l_[PADL_(u_int)]; u_int highfd; char highfd_r_[PADR_(u_int)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2183,6 +2188,7 @@ int sys_fhlink(struct thread *, struct fhlink_args *); int sys_fhlinkat(struct thread *, struct fhlinkat_args *); int sys_fhreadlink(struct thread *, struct fhreadlink_args *); int sys___sysctlbyname(struct thread *, struct __sysctlbyname_args *); +int sys_close_range(struct thread *, struct close_range_args *); #ifdef COMPAT_43 @@ -3085,6 +3091,7 @@ int freebsd11_mknodat(struct thread *, struct freebsd1 #define SYS_AUE_fhlinkat AUE_NULL #define SYS_AUE_fhreadlink AUE_NULL #define SYS_AUE___sysctlbyname AUE_SYSCTL +#define SYS_AUE_close_range AUE_CLOSERANGE #undef PAD_ #undef PADL_ Modified: stable/12/tests/sys/file/closefrom_test.c ============================================================================== --- stable/12/tests/sys/file/closefrom_test.c Wed Aug 5 03:30:03 2020 (r363878) +++ stable/12/tests/sys/file/closefrom_test.c Wed Aug 5 03:53:57 2020 (r363879) @@ -146,7 +146,7 @@ main(void) pid_t pid; int fd, i, start; - printf("1..15\n"); + printf("1..20\n"); /* We better start up with fd's 0, 1, and 2 open. */ start = devnull(); @@ -270,6 +270,60 @@ main(void) if (fd != 3) 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"); + + /* Fork a child process to test closefrom(0) twice. */ + pid = fork(); + if (pid < 0) + fail_err("fork"); + if (pid == 0) { + /* Child. */ + closefrom(0); + closefrom(0); + cok(info, "closefrom(0)"); + } + if (wait(NULL) < 0) + fail_err("wait"); + if (info->failed) + fail(info->tag, "%s", info->message); + ok(info->tag); return (0); }