fd: add close_range(..., CLOSE_RANGE_CLOEXEC)
For compatibility with Linux. MFC after: 3 days Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D34424
This commit is contained in:
parent
33cbbf268f
commit
f3f3e3c44d
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 12, 2020
|
||||
.Dd March 3, 2022
|
||||
.Dt CLOSEFROM 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -56,8 +56,12 @@ 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 .
|
||||
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
|
||||
|
@ -400,6 +400,13 @@ sysdecode_cap_fcntlrights(FILE *fp, uint32_t rights, uint32_t *rem)
|
||||
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)
|
||||
{
|
||||
|
@ -94,6 +94,7 @@ gen_table "accessmode" "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+" "sys/
|
||||
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"
|
||||
|
@ -43,6 +43,7 @@ const char *sysdecode_atfd(int _fd);
|
||||
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);
|
||||
|
@ -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"
|
||||
|
@ -1393,24 +1393,40 @@ kern_close(struct thread *td, int fd)
|
||||
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;
|
||||
struct fdescenttbl *fdt;
|
||||
struct filedescent *fde;
|
||||
int fd;
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
@ -1440,6 +1456,26 @@ kern_close_range(struct thread *td, u_int lowfd, u_int highfd)
|
||||
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 @@ sys_close_range(struct thread *td, struct close_range_args *uap)
|
||||
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 @@ freebsd12_closefrom(struct thread *td, struct freebsd12_closefrom_args *uap)
|
||||
* 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 */
|
||||
|
||||
|
@ -111,7 +111,7 @@ int kern_clock_settime(struct thread *td, clockid_t clock_id,
|
||||
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);
|
||||
|
@ -200,6 +200,11 @@
|
||||
|
||||
#define SWAPOFF_FORCE 0x00000001
|
||||
|
||||
/*
|
||||
* close_range() options.
|
||||
*/
|
||||
#define CLOSE_RANGE_CLOEXEC (1<<2)
|
||||
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
#endif /* !_SYS_UNISTD_H_ */
|
||||
|
@ -144,7 +144,7 @@ main(void)
|
||||
{
|
||||
struct shared_info *info;
|
||||
pid_t pid;
|
||||
int fd, i, start;
|
||||
int fd, flags, i, start;
|
||||
|
||||
printf("1..20\n");
|
||||
|
||||
@ -325,5 +325,38 @@ main(void)
|
||||
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);
|
||||
}
|
||||
|
@ -864,6 +864,14 @@ ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags)
|
||||
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);
|
||||
|
@ -91,6 +91,7 @@ enum Argtype {
|
||||
Atfd,
|
||||
Atflags,
|
||||
CapFcntlRights,
|
||||
Closerangeflags,
|
||||
Extattrnamespace,
|
||||
Fadvice,
|
||||
Fcntl,
|
||||
|
@ -183,6 +183,8 @@ static const struct syscall_decode decoded_syscalls[] = {
|
||||
.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 @@ print_arg(struct syscall_arg *sc, unsigned long *args, register_t *retval,
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user