Page MenuHomeFreeBSD

D34424.diff
No OneTemporary

D34424.diff

diff --git a/lib/libc/sys/closefrom.2 b/lib/libc/sys/closefrom.2
--- a/lib/libc/sys/closefrom.2
+++ b/lib/libc/sys/closefrom.2
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 12, 2020
+.Dd March 3, 2022
.Dt CLOSEFROM 2
.Os
.Sh NAME
@@ -56,8 +56,12 @@
.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 .
+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.
+.El
.Sh RETURN VALUES
Upon successful completion,
.Fn close_range
diff --git a/lib/libsysdecode/flags.c b/lib/libsysdecode/flags.c
--- a/lib/libsysdecode/flags.c
+++ b/lib/libsysdecode/flags.c
@@ -400,6 +400,13 @@
return (print_mask_int(fp, capfcntl, rights, rem));
}
+bool
+sysdecode_close_range_flags(FILE *fp, int flags, int *rem)
+{
+
+ return (print_mask_int(fp, closerangeflags, flags, rem));
+}
+
const char *
sysdecode_extattrnamespace(int namespace)
{
diff --git a/lib/libsysdecode/mktables b/lib/libsysdecode/mktables
--- a/lib/libsysdecode/mktables
+++ b/lib/libsysdecode/mktables
@@ -94,6 +94,7 @@
gen_table "acltype" "ACL_TYPE_[A-Z4_]+[[:space:]]+0x[0-9]+" "sys/acl.h"
gen_table "atflags" "AT_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/fcntl.h"
gen_table "capfcntl" "CAP_FCNTL_[A-Z]+[[:space:]]+\(1" "sys/capsicum.h"
+gen_table "closerangeflags" "CLOSE_RANGE_[A-Z]+[[:space:]]+\([0-9]+<<[0-9]+\)" "sys/unistd.h"
gen_table "extattrns" "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/extattr.h"
gen_table "fadvisebehav" "POSIX_FADV_[A-Z]+[[:space:]]+[0-9]+" "sys/fcntl.h"
gen_table "openflags" "O_[A-Z]+[[:space:]]+0x[0-9A-Fa-f]+" "sys/fcntl.h" "O_RDONLY|O_RDWR|O_WRONLY"
diff --git a/lib/libsysdecode/sysdecode.h b/lib/libsysdecode/sysdecode.h
--- a/lib/libsysdecode/sysdecode.h
+++ b/lib/libsysdecode/sysdecode.h
@@ -43,6 +43,7 @@
bool sysdecode_atflags(FILE *_fp, int _flags, int *_rem);
bool sysdecode_cap_fcntlrights(FILE *_fp, uint32_t _rights, uint32_t *_rem);
void sysdecode_cap_rights(FILE *_fp, cap_rights_t *_rightsp);
+bool sysdecode_close_range_flags(FILE *_fp, int _flags, int *_rem);
const char *sysdecode_cmsg_type(int _cmsg_level, int _cmsg_type);
const char *sysdecode_extattrnamespace(int _namespace);
const char *sysdecode_fadvice(int _advice);
diff --git a/lib/libsysdecode/sysdecode_mask.3 b/lib/libsysdecode/sysdecode_mask.3
--- a/lib/libsysdecode/sysdecode_mask.3
+++ b/lib/libsysdecode/sysdecode_mask.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 16, 2018
+.Dd March 3, 2022
.Dt sysdecode_mask 3
.Os
.Sh NAME
@@ -32,6 +32,7 @@
.Nm sysdecode_accessmode ,
.Nm sysdecode_atflags ,
.Nm sysdecode_capfcntlrights ,
+.Nm sysdecode_close_range_flags ,
.Nm sysdecode_fcntl_fileflags ,
.Nm sysdecode_fileflags ,
.Nm sysdecode_filemode ,
@@ -74,6 +75,8 @@
.Ft bool
.Fn sysdecode_cap_fcntlrights "FILE *fp" "uint32_t rights" "uint32_t *rem"
.Ft bool
+.Fn sysdecode_close_range_flags "FILE *fp" "int flags" "int *rem"
+.Ft bool
.Fn sysdecode_fcntl_fileflags "FILE *fp" "int flags" "int *rem"
.Ft bool
.Fn sysdecode_fileflags "FILE *fp" "fflags_t flags" "fflags_t *rem"
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1393,23 +1393,39 @@
return (closefp(fdp, fd, fp, td, true, true));
}
-int
-kern_close_range(struct thread *td, u_int lowfd, u_int highfd)
+static int
+close_range_cloexec(struct thread *td, u_int lowfd, u_int highfd)
{
struct filedesc *fdp;
- const struct fdescenttbl *fdt;
- struct file *fp;
+ struct fdescenttbl *fdt;
+ struct filedescent *fde;
int fd;
- /*
- * 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) {
- return (EINVAL);
+ fdp = td->td_proc->p_fd;
+ FILEDESC_XLOCK(fdp);
+ fdt = atomic_load_ptr(&fdp->fd_files);
+ highfd = MIN(highfd, fdt->fdt_nfiles - 1);
+ fd = lowfd;
+ if (__predict_false(fd > highfd)) {
+ goto out_locked;
+ }
+ for (; fd <= highfd; fd++) {
+ fde = &fdt->fdt_ofiles[fd];
+ if (fde->fde_file != NULL)
+ fde->fde_flags |= UF_EXCLOSE;
}
+out_locked:
+ FILEDESC_XUNLOCK(fdp);
+ return (0);
+}
+
+static int
+close_range_impl(struct thread *td, u_int lowfd, u_int highfd)
+{
+ struct filedesc *fdp;
+ const struct fdescenttbl *fdt;
+ struct file *fp;
+ int fd;
fdp = td->td_proc->p_fd;
FILEDESC_XLOCK(fdp);
@@ -1440,6 +1456,26 @@
return (0);
}
+int
+kern_close_range(struct thread *td, int flags, u_int lowfd, u_int highfd)
+{
+
+ /*
+ * 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) {
+ return (EINVAL);
+ }
+
+ if ((flags & CLOSE_RANGE_CLOEXEC) != 0)
+ return (close_range_cloexec(td, lowfd, highfd));
+
+ return (close_range_impl(td, lowfd, highfd));
+}
+
#ifndef _SYS_SYSPROTO_H_
struct close_range_args {
u_int lowfd;
@@ -1455,10 +1491,9 @@
AUDIT_ARG_CMD(uap->highfd);
AUDIT_ARG_FFLAGS(uap->flags);
- /* No flags currently defined */
- if (uap->flags != 0)
+ if ((uap->flags & ~(CLOSE_RANGE_CLOEXEC)) != 0)
return (EINVAL);
- return (kern_close_range(td, uap->lowfd, uap->highfd));
+ return (kern_close_range(td, uap->flags, uap->lowfd, uap->highfd));
}
#ifdef COMPAT_FREEBSD12
@@ -1483,7 +1518,7 @@
* closefrom(0) which closes all files.
*/
lowfd = MAX(0, uap->lowfd);
- return (kern_close_range(td, lowfd, ~0U));
+ return (kern_close_range(td, 0, lowfd, ~0U));
}
#endif /* COMPAT_FREEBSD12 */
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -111,7 +111,7 @@
struct timespec *ats);
void kern_thread_cputime(struct thread *targettd, struct timespec *ats);
void kern_process_cputime(struct proc *targetp, struct timespec *ats);
-int kern_close_range(struct thread *td, u_int lowfd, u_int highfd);
+int kern_close_range(struct thread *td, int flags, 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);
diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h
--- a/sys/sys/unistd.h
+++ b/sys/sys/unistd.h
@@ -200,6 +200,11 @@
#define SWAPOFF_FORCE 0x00000001
+/*
+ * close_range() options.
+ */
+#define CLOSE_RANGE_CLOEXEC (1<<2)
+
#endif /* __BSD_VISIBLE */
#endif /* !_SYS_UNISTD_H_ */
diff --git a/tests/sys/file/closefrom_test.c b/tests/sys/file/closefrom_test.c
--- a/tests/sys/file/closefrom_test.c
+++ b/tests/sys/file/closefrom_test.c
@@ -144,7 +144,7 @@
{
struct shared_info *info;
pid_t pid;
- int fd, i, start;
+ int fd, flags, i, start;
printf("1..20\n");
@@ -325,5 +325,38 @@
fail(info->tag, "%s", info->message);
ok(info->tag);
+ /* test CLOSE_RANGE_CLOEXEC */
+ for (i = 0; i < 8; i++)
+ (void)devnull();
+ fd = highest_fd();
+ start = fd - 8;
+ if (close_range(start + 1, start + 4, CLOSE_RANGE_CLOEXEC) < 0)
+ fail_err("close_range(..., CLOSE_RANGE_CLOEXEC)");
+ flags = fcntl(start, F_GETFD);
+ if (flags < 0)
+ fail_err("fcntl(.., F_GETFD)");
+ if ((flags & FD_CLOEXEC) != 0)
+ fail("close_range", "CLOSE_RANGE_CLOEXEC set close-on-exec "
+ "when it should not have on fd %d", start);
+ for (i = start + 1; i <= start + 4; i++) {
+ flags = fcntl(i, F_GETFD);
+ if (flags < 0)
+ fail_err("fcntl(.., F_GETFD)");
+ if ((flags & FD_CLOEXEC) == 0)
+ fail("close_range", "CLOSE_RANGE_CLOEXEC did not set "
+ "close-on-exec on fd %d", i);
+ }
+ for (; i < start + 8; i++) {
+ flags = fcntl(i, F_GETFD);
+ if (flags < 0)
+ fail_err("fcntl(.., F_GETFD)");
+ if ((flags & FD_CLOEXEC) != 0)
+ fail("close_range", "CLOSE_RANGE_CLOEXEC set close-on-exec "
+ "when it should not have on fd %d", i);
+ }
+ if (close_range(start, start + 8, 0) < 0)
+ fail_err("close_range");
+ ok("close_range(..., CLOSE_RANGE_CLOEXEC)");
+
return (0);
}
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -864,6 +864,14 @@
ip++;
narg--;
break;
+ case SYS_close_range:
+ print_number(ip, narg, c);
+ print_number(ip, narg, c);
+ putchar(',');
+ print_mask_arg(sysdecode_close_range_flags, *ip);
+ ip += 3;
+ narg -= 3;
+ break;
case SYS_open:
case SYS_openat:
print_number(ip, narg, c);
diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h
--- a/usr.bin/truss/syscall.h
+++ b/usr.bin/truss/syscall.h
@@ -91,6 +91,7 @@
Atfd,
Atflags,
CapFcntlRights,
+ Closerangeflags,
Extattrnamespace,
Fadvice,
Fcntl,
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -183,6 +183,8 @@
.args = { { Int, 0 } } },
{ .name = "closefrom", .ret_type = 1, .nargs = 1,
.args = { { Int, 0 } } },
+ { .name = "close_range", .ret_type = 1, .nargs = 3,
+ .args = { { Int, 0 }, { Int, 1 }, { Closerangeflags, 2 } } },
{ .name = "compat11.fstat", .ret_type = 1, .nargs = 2,
.args = { { Int, 0 }, { Stat11 | OUT, 1 } } },
{ .name = "compat11.fstatat", .ret_type = 1, .nargs = 4,
@@ -1983,6 +1985,9 @@
case Fcntl:
print_integer_arg(sysdecode_fcntl_cmd, fp, args[sc->offset]);
break;
+ case Closerangeflags:
+ print_mask_arg(sysdecode_close_range_flags, fp, args[sc->offset]);
+ break;
case Mprot:
print_mask_arg(sysdecode_mmap_prot, fp, args[sc->offset]);
break;

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 24, 2:31 AM (21 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16071956
Default Alt Text
D34424.diff (9 KB)

Event Timeline