From cbd92ce62e92bd17871c9668c2c2bebac3e2ac2e Mon Sep 17 00:00:00 2001 From: Matt Macy Date: Wed, 9 May 2018 18:47:24 +0000 Subject: Eliminate the overhead of gratuitous repeated reinitialization of cap_rights - Add macros to allow preinitialization of cap_rights_t. - Convert most commonly used code paths to use preinitialized cap_rights_t. A 3.6% speedup in fstat was measured with this change. Reported by: mjg Reviewed by: oshogbo Approved by: sbruno MFC after: 1 month --- sys/cddl/compat/opensolaris/sys/file.h | 3 +- .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 14 +--- .../opensolaris/uts/common/fs/zfs/zfs_onexit.c | 2 +- sys/compat/cloudabi/cloudabi_file.c | 6 +- sys/compat/linux/linux_event.c | 6 +- sys/compat/linux/linux_file.c | 13 +--- sys/compat/linux/linux_ioctl.c | 54 ++++++-------- sys/compat/linux/linux_mmap.c | 3 +- sys/compat/linux/linux_socket.c | 7 +- sys/compat/linux/linux_stats.c | 6 +- sys/compat/linuxkpi/common/include/linux/file.h | 9 +-- sys/dev/filemon/filemon.c | 3 +- sys/dev/hwpmc/hwpmc_logging.c | 4 +- sys/fs/fdescfs/fdesc_vnops.c | 6 +- sys/fs/fuse/fuse_vfsops.c | 3 +- sys/kern/kern_descrip.c | 35 +++------ sys/kern/kern_event.c | 4 +- sys/kern/kern_exec.c | 4 +- sys/kern/kern_sendfile.c | 8 +- sys/kern/kern_sig.c | 4 +- sys/kern/subr_capability.c | 44 ++++++++++- sys/kern/sys_generic.c | 37 +++------ sys/kern/sys_procdesc.c | 4 +- sys/kern/uipc_mqueue.c | 15 +--- sys/kern/uipc_sem.c | 6 +- sys/kern/uipc_syscalls.c | 30 +++----- sys/kern/vfs_aio.c | 14 ++-- sys/kern/vfs_syscalls.c | 15 ++-- sys/netsmb/smb_dev.c | 3 +- sys/sys/capsicum.h | 87 ++++++++++++++++++++++ 30 files changed, 232 insertions(+), 217 deletions(-) diff --git a/sys/cddl/compat/opensolaris/sys/file.h b/sys/cddl/compat/opensolaris/sys/file.h index f392d9e9154a..04851ee86d6d 100644 --- a/sys/cddl/compat/opensolaris/sys/file.h +++ b/sys/cddl/compat/opensolaris/sys/file.h @@ -52,10 +52,9 @@ static __inline void releasef(int fd) { struct file *fp; - cap_rights_t rights; /* No CAP_ rights required, as we're only releasing. */ - if (fget(curthread, fd, cap_rights_init(&rights), &fp) == 0) { + if (fget(curthread, fd, &cap_no_rights, &fp) == 0) { fdrop(fp, curthread); fdrop(fp, curthread); } diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 1f8c85f1f082..bd5e988dfd22 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -4446,7 +4446,6 @@ zfs_ioc_recv(zfs_cmd_t *zc) char *origin = NULL; char *tosnap; char tofs[ZFS_MAX_DATASET_NAME_LEN]; - cap_rights_t rights; boolean_t first_recvd_props = B_FALSE; if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 || @@ -4467,7 +4466,7 @@ zfs_ioc_recv(zfs_cmd_t *zc) #ifdef illumos fp = getf(fd); #else - fget_read(curthread, fd, cap_rights_init(&rights, CAP_PREAD), &fp); + fget_read(curthread, fd, &cap_pread_rights, &fp); #endif if (fp == NULL) { nvlist_free(props); @@ -4744,13 +4743,11 @@ zfs_ioc_send(zfs_cmd_t *zc) dsl_pool_rele(dp, FTAG); } else { file_t *fp; - cap_rights_t rights; #ifdef illumos fp = getf(zc->zc_cookie); #else - fget_write(curthread, zc->zc_cookie, - cap_rights_init(&rights, CAP_WRITE), &fp); + fget_write(curthread, zc->zc_cookie, &cap_write_rights, &fp); #endif if (fp == NULL) return (SET_ERROR(EBADF)); @@ -5387,15 +5384,13 @@ static int zfs_ioc_diff(zfs_cmd_t *zc) { file_t *fp; - cap_rights_t rights; offset_t off; int error; #ifdef illumos fp = getf(zc->zc_cookie); #else - fget_write(curthread, zc->zc_cookie, - cap_rights_init(&rights, CAP_WRITE), &fp); + fget_write(curthread, zc->zc_cookie, &cap_write_rights, &fp); #endif if (fp == NULL) return (SET_ERROR(EBADF)); @@ -5787,7 +5782,6 @@ zfs_ioc_unjail(zfs_cmd_t *zc) static int zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl) { - cap_rights_t rights; file_t *fp; int error; offset_t off; @@ -5815,7 +5809,7 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl) #ifdef illumos file_t *fp = getf(fd); #else - fget_write(curthread, fd, cap_rights_init(&rights, CAP_WRITE), &fp); + fget_write(curthread, fd, &cap_write_rights, &fp); #endif if (fp == NULL) return (SET_ERROR(EBADF)); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c index fe023996dd89..edb9ca86caa8 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c @@ -126,7 +126,7 @@ zfs_onexit_fd_hold(int fd, minor_t *minorp) void *data; int error; - fp = getf(fd, cap_rights_init(&rights)); + fp = getf(fd, &cap_no_rights); if (fp == NULL) return (SET_ERROR(EBADF)); diff --git a/sys/compat/cloudabi/cloudabi_file.c b/sys/compat/cloudabi/cloudabi_file.c index 5811c0bbb314..19f13570b77d 100644 --- a/sys/compat/cloudabi/cloudabi_file.c +++ b/sys/compat/cloudabi/cloudabi_file.c @@ -390,12 +390,11 @@ cloudabi_sys_file_readdir(struct thread *td, struct file *fp; struct vnode *vp; void *readbuf; - cap_rights_t rights; cloudabi_dircookie_t offset; int error; /* Obtain directory vnode. */ - error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, uap->fd, &cap_read_rights, &fp); if (error != 0) { if (error == EINVAL) return (ENOTDIR); @@ -559,14 +558,13 @@ cloudabi_sys_file_stat_fget(struct thread *td, struct stat sb; cloudabi_filestat_t csb; struct file *fp; - cap_rights_t rights; cloudabi_filetype_t filetype; int error; memset(&csb, 0, sizeof(csb)); /* Fetch file descriptor attributes. */ - error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FSTAT), &fp); + error = fget(td, uap->fd, &cap_fstat_rights, &fp); if (error != 0) return (error); error = fo_stat(fp, &sb, td->td_ucred, td); diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c index e2779b4fb12b..91062bc483cd 100644 --- a/sys/compat/linux/linux_event.c +++ b/sys/compat/linux/linux_event.c @@ -1190,14 +1190,13 @@ linux_timerfd_curval(struct timerfd *tfd, struct itimerspec *ots) int linux_timerfd_gettime(struct thread *td, struct linux_timerfd_gettime_args *args) { - cap_rights_t rights; struct l_itimerspec lots; struct itimerspec ots; struct timerfd *tfd; struct file *fp; int error; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_READ), &fp); + error = fget(td, args->fd, &cap_read_rights, &fp); if (error != 0) return (error); tfd = fp->f_data; @@ -1225,7 +1224,6 @@ linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args struct l_itimerspec lots; struct itimerspec nts, ots; struct timespec cts, ts; - cap_rights_t rights; struct timerfd *tfd; struct timeval tv; struct file *fp; @@ -1241,7 +1239,7 @@ linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args if (error != 0) return (error); - error = fget(td, args->fd, cap_rights_init(&rights, CAP_WRITE), &fp); + error = fget(td, args->fd, &cap_write_rights, &fp); if (error != 0) return (error); tfd = fp->f_data; diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 2e02966e6d5a..36025934f577 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -89,7 +89,6 @@ linux_creat(struct thread *td, struct linux_creat_args *args) static int linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode) { - cap_rights_t rights; struct proc *p = td->td_proc; struct file *fp; int fd; @@ -144,7 +143,7 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod * checking below. */ fd = td->td_retval[0]; - if (fget(td, fd, cap_rights_init(&rights, CAP_IOCTL), &fp) == 0) { + if (fget(td, fd, &cap_ioctl_rights, &fp) == 0) { if (fp->f_type != DTYPE_VNODE) { fdrop(fp, td); goto done; @@ -263,13 +262,12 @@ linux_llseek(struct thread *td, struct linux_llseek_args *args) static int linux_getdents_error(struct thread *td, int fd, int err) { - cap_rights_t rights; struct vnode *vp; struct file *fp; int error; /* Linux return ENOTDIR in case when fd is not a directory. */ - error = getvnode(td, fd, cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, fd, &cap_read_rights, &fp); if (error != 0) return (error); vp = fp->f_vnode; @@ -985,15 +983,13 @@ linux_fdatasync(td, uap) int linux_pread(struct thread *td, struct linux_pread_args *uap) { - cap_rights_t rights; struct vnode *vp; int error; error = kern_pread(td, uap->fd, uap->buf, uap->nbyte, uap->offset); if (error == 0) { /* This seems to violate POSIX but Linux does it. */ - error = fgetvp(td, uap->fd, - cap_rights_init(&rights, CAP_PREAD), &vp); + error = fgetvp(td, uap->fd, &cap_pread_rights, &vp); if (error != 0) return (error); if (vp->v_type == VDIR) { @@ -1275,7 +1271,6 @@ fcntl_common(struct thread *td, struct linux_fcntl_args *args) { struct l_flock linux_flock; struct flock bsd_flock; - cap_rights_t rights; struct file *fp; long arg; int error, result; @@ -1379,7 +1374,7 @@ fcntl_common(struct thread *td, struct linux_fcntl_args *args) * pipes under Linux-2.2.35 at least). */ error = fget(td, args->fd, - cap_rights_init(&rights, CAP_FCNTL), &fp); + &cap_fcntl_rights, &fp); if (error) return (error); if (fp->f_type == DTYPE_PIPE) { diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 65591f127742..30b565c20b69 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -194,13 +194,12 @@ struct linux_hd_big_geometry { static int linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; int error; u_int sectorsize, fwcylinders, fwheads, fwsectors; off_t mediasize, bytespercyl; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); switch (args->cmd & 0xffff) { @@ -278,13 +277,12 @@ linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; int error; u_int sectorsize; off_t mediasize; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); switch (args->cmd & 0xffff) { @@ -717,11 +715,10 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args) struct termios bios; struct linux_termios lios; struct linux_termio lio; - cap_rights_t rights; struct file *fp; int error; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); @@ -1461,11 +1458,10 @@ bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp) static int linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; int error; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); switch (args->cmd & 0xffff) { @@ -1998,11 +1994,10 @@ linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; int error; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); switch (args->cmd & 0xffff) { @@ -2411,7 +2406,6 @@ static int linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) { char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ]; - cap_rights_t rights; struct ifnet *ifp; struct file *fp; int error, type; @@ -2419,7 +2413,7 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) ifp = NULL; error = 0; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); type = fp->f_type; @@ -2649,11 +2643,10 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; int error, type; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); type = fp->f_type; @@ -2685,11 +2678,10 @@ linux_ioctl_sg_io(struct thread *td, struct linux_ioctl_args *args) { struct sg_io_hdr io; struct sg_io_hdr32 io32; - cap_rights_t rights; struct file *fp; int error; - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) { printf("sg_linux_ioctl: fget returned %d\n", error); return (error); @@ -2997,7 +2989,6 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw) static int linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; int error; struct video_tuner vtun; @@ -3016,7 +3007,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCGTUNER: error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun)); @@ -3036,7 +3027,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCSTUNER: error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun)); @@ -3055,7 +3046,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCGWIN: error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td); @@ -3069,7 +3060,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCSWIN: error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin)); @@ -3094,7 +3085,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCGFBUF: error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td); @@ -3108,7 +3099,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCSFBUF: error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf)); @@ -3138,7 +3129,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCSMICROCODE: error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode)); @@ -3302,7 +3293,6 @@ bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf) static int linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; int error; struct v4l2_format vformat; @@ -3395,7 +3385,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) if (error) return (error); error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error) return (error); if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0) @@ -3420,7 +3410,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) return (error); linux_to_bsd_v4l2_standard(&l_vstd, &vstd); error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error) return (error); error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd, @@ -3444,7 +3434,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) if (error != 0) return (error); error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp, @@ -3465,7 +3455,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) if (error) return (error); error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error) return (error); linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf); @@ -3640,7 +3630,6 @@ linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args) static int linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; clockid_t clock; int error; @@ -3668,7 +3657,7 @@ linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args) return (error); error = fget(td, args->fd, - cap_rights_init(&rights, CAP_IOCTL), &fp); + &cap_ioctl_rights, &fp); if (error != 0) return (error); @@ -3694,7 +3683,6 @@ linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args) int linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { - cap_rights_t rights; struct file *fp; struct handler_element *he; int error, cmd; @@ -3705,7 +3693,7 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args *args) (unsigned long)args->cmd); #endif - error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, args->fd, &cap_ioctl_rights, &fp); if (error != 0) return (error); if ((fp->f_flag & (FREAD|FWRITE)) == 0) { diff --git a/sys/compat/linux/linux_mmap.c b/sys/compat/linux/linux_mmap.c index 94dec5ae56a1..70d274c5aca1 100644 --- a/sys/compat/linux/linux_mmap.c +++ b/sys/compat/linux/linux_mmap.c @@ -72,7 +72,6 @@ linux_mmap_common(struct thread *td, uintptr_t addr, size_t len, int prot, int bsd_flags, error; struct file *fp; - cap_rights_t rights; LINUX_CTR6(mmap2, "0x%lx, %ld, %ld, 0x%08lx, %ld, 0x%lx", addr, len, prot, flags, fd, pos); @@ -126,7 +125,7 @@ linux_mmap_common(struct thread *td, uintptr_t addr, size_t len, int prot, * protection options specified. */ - error = fget(td, fd, cap_rights_init(&rights, CAP_MMAP), &fp); + error = fget(td, fd, &cap_mmap_rights, &fp); if (error != 0) return (error); if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_DEV) { diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 0887374f4e70..604627048ed0 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -766,7 +766,6 @@ linux_bind(struct thread *td, struct linux_bind_args *args) int linux_connect(struct thread *td, struct linux_connect_args *args) { - cap_rights_t rights; struct socket *so; struct sockaddr *sa; struct file *fp; @@ -788,7 +787,7 @@ linux_connect(struct thread *td, struct linux_connect_args *args) * when on a non-blocking socket. Instead it returns the * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. */ - error = getsock_cap(td, args->s, cap_rights_init(&rights, CAP_CONNECT), + error = getsock_cap(td, args->s, &cap_connect_rights, &fp, &fflag, NULL); if (error != 0) return (error); @@ -824,7 +823,6 @@ linux_accept_common(struct thread *td, int s, l_uintptr_t addr, socklen_t * __restrict anamelen; int flags; } */ bsd_args; - cap_rights_t rights; struct socket *so; struct file *fp; int error, error1; @@ -842,8 +840,7 @@ linux_accept_common(struct thread *td, int s, l_uintptr_t addr, if (error == EFAULT && namelen != sizeof(struct sockaddr_in)) return (EINVAL); if (error == EINVAL) { - error1 = getsock_cap(td, s, - cap_rights_init(&rights, CAP_ACCEPT), &fp, NULL, NULL); + error1 = getsock_cap(td, s, &cap_accept_rights, &fp, NULL, NULL); if (error1 != 0) return (error1); so = fp->f_data; diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index aae8ae3fe0ff..56cb38ad0f9e 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -103,14 +103,13 @@ translate_fd_major_minor(struct thread *td, int fd, struct stat *buf) { struct file *fp; struct vnode *vp; - cap_rights_t rights; int major, minor; /* * No capability rights required here. */ if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) || - fget(td, fd, cap_rights_init(&rights), &fp) != 0) + fget(td, fd, &cap_no_rights, &fp) != 0) return; vp = fp->f_vnode; if (vp != NULL && vp->v_rdev != NULL && @@ -680,12 +679,11 @@ linux_newfstatat(struct thread *td, struct linux_newfstatat_args *args) int linux_syncfs(struct thread *td, struct linux_syncfs_args *args) { - cap_rights_t rights; struct mount *mp; struct vnode *vp; int error, save; - error = fgetvp(td, args->fd, cap_rights_init(&rights, CAP_FSYNC), &vp); + error = fgetvp(td, args->fd, &cap_fsync_rights, &vp); if (error != 0) /* * Linux syncfs() returns only EBADF, however fgetvp() diff --git a/sys/compat/linuxkpi/common/include/linux/file.h b/sys/compat/linuxkpi/common/include/linux/file.h index 41fab51a696f..acbb43bac1b5 100644 --- a/sys/compat/linuxkpi/common/include/linux/file.h +++ b/sys/compat/linuxkpi/common/include/linux/file.h @@ -50,12 +50,11 @@ extern struct fileops linuxfileops; static inline struct linux_file * linux_fget(unsigned int fd) { - cap_rights_t rights; struct file *file; /* lookup file pointer by file descriptor index */ if (fget_unlocked(curthread->td_proc->p_fd, fd, - cap_rights_init(&rights), &file, NULL) != 0) + &cap_no_rights, &file, NULL) != 0) return (NULL); /* check if file handle really belongs to us */ @@ -88,11 +87,10 @@ file_count(struct linux_file *filp) static inline void put_unused_fd(unsigned int fd) { - cap_rights_t rights; struct file *file; if (fget_unlocked(curthread->td_proc->p_fd, fd, - cap_rights_init(&rights), &file, NULL) != 0) { + &cap_no_rights, &file, NULL) != 0) { return; } /* @@ -109,11 +107,10 @@ put_unused_fd(unsigned int fd) static inline void fd_install(unsigned int fd, struct linux_file *filp) { - cap_rights_t rights; struct file *file; if (fget_unlocked(curthread->td_proc->p_fd, fd, - cap_rights_init(&rights), &file, NULL) != 0) { + &cap_no_rights, &file, NULL) != 0) { filp->_file = NULL; } else { filp->_file = file; diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c index 38c4eb3f4a56..80c3c28ff51a 100644 --- a/sys/dev/filemon/filemon.c +++ b/sys/dev/filemon/filemon.c @@ -361,7 +361,6 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused, int error = 0; struct filemon *filemon; struct proc *p; - cap_rights_t rights; if ((error = devfs_get_cdevpriv((void **) &filemon)) != 0) return (error); @@ -377,7 +376,7 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused, } error = fget_write(td, *(int *)data, - cap_rights_init(&rights, CAP_PWRITE), + &cap_pwrite_rights, &filemon->fp); if (error == 0) /* Write the file header. */ diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c index fbc7dc769adc..0804a4542272 100644 --- a/sys/dev/hwpmc/hwpmc_logging.c +++ b/sys/dev/hwpmc/hwpmc_logging.c @@ -638,7 +638,6 @@ int pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd) { struct proc *p; - cap_rights_t rights; int error; sx_assert(&pmc_sx, SA_XLOCKED); @@ -655,8 +654,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd) po->po_file)); /* get a reference to the file state */ - error = fget_write(curthread, logfd, - cap_rights_init(&rights, CAP_WRITE), &po->po_file); + error = fget_write(curthread, logfd, &cap_write_rights, &po->po_file); if (error) goto error; diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index 30ce286074b6..7d94ddf17a51 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -286,7 +286,6 @@ fdesc_lookup(struct vop_lookup_args *ap) struct thread *td = cnp->cn_thread; struct file *fp; struct fdesc_get_ino_args arg; - cap_rights_t rights; int nlen = cnp->cn_namelen; u_int fd, fd1; int error; @@ -331,7 +330,7 @@ fdesc_lookup(struct vop_lookup_args *ap) /* * No rights to check since 'fp' isn't actually used. */ - if ((error = fget(td, fd, cap_rights_init(&rights), &fp)) != 0) + if ((error = fget(td, fd, &cap_no_rights, &fp)) != 0) goto bad; /* Check if we're looking up ourselves. */ @@ -613,7 +612,6 @@ static int fdesc_readlink(struct vop_readlink_args *va) { struct vnode *vp, *vn; - cap_rights_t rights; struct thread *td; struct uio *uio; struct file *fp; @@ -631,7 +629,7 @@ fdesc_readlink(struct vop_readlink_args *va) VOP_UNLOCK(vn, 0); td = curthread; - error = fget_cap(td, fd_fd, cap_rights_init(&rights), &fp, NULL); + error = fget_cap(td, fd_fd, &cap_no_rights, &fp, NULL); if (error != 0) goto out; diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c index 700d4450c2e7..0be6185e558e 100644 --- a/sys/fs/fuse/fuse_vfsops.c +++ b/sys/fs/fuse/fuse_vfsops.c @@ -222,7 +222,6 @@ fuse_vfsop_mount(struct mount *mp) struct file *fp, *fptmp; char *fspec, *subtype; struct vfsoptlist *opts; - cap_rights_t rights; subtype = NULL; max_read_set = 0; @@ -292,7 +291,7 @@ fuse_vfsop_mount(struct mount *mp) FS_DEBUG2G("mntopts 0x%jx\n", (uintmax_t)mntopts); - err = fget(td, fd, cap_rights_init(&rights, CAP_READ), &fp); + err = fget(td, fd, &cap_read_rights, &fp); if (err != 0) { FS_DEBUG("invalid or not opened device: data=%p\n", data); goto out; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 8e6164f4a9f5..5a2594ea303e 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -490,7 +490,6 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) struct filedescent *fde; struct proc *p; struct vnode *vp; - cap_rights_t rights; int error, flg, tmp; uint64_t bsize; off_t foffset; @@ -548,8 +547,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_GETFL: - error = fget_fcntl(td, fd, - cap_rights_init(&rights, CAP_FCNTL), F_GETFL, &fp); + error = fget_fcntl(td, fd, &cap_fcntl_rights, F_GETFL, &fp); if (error != 0) break; td->td_retval[0] = OFLAGS(fp->f_flag); @@ -557,8 +555,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_SETFL: - error = fget_fcntl(td, fd, - cap_rights_init(&rights, CAP_FCNTL), F_SETFL, &fp); + error = fget_fcntl(td, fd, &cap_fcntl_rights, F_SETFL, &fp); if (error != 0) break; do { @@ -585,8 +582,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_GETOWN: - error = fget_fcntl(td, fd, - cap_rights_init(&rights, CAP_FCNTL), F_GETOWN, &fp); + error = fget_fcntl(td, fd, &cap_fcntl_rights, F_GETOWN, &fp); if (error != 0) break; error = fo_ioctl(fp, FIOGETOWN, &tmp, td->td_ucred, td); @@ -596,8 +592,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_SETOWN: - error = fget_fcntl(td, fd, - cap_rights_init(&rights, CAP_FCNTL), F_SETOWN, &fp); + error = fget_fcntl(td, fd, &cap_fcntl_rights, F_SETOWN, &fp); if (error != 0) break; tmp = arg; @@ -618,8 +613,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) case F_SETLK: do_setlk: - cap_rights_init(&rights, CAP_FLOCK); - error = fget_unlocked(fdp, fd, &rights, &fp, NULL); + error = fget_unlocked(fdp, fd, &cap_flock_rights, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -711,7 +705,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) * that the closing thread was a bit slower and that the * advisory lock succeeded before the close. */ - error = fget_unlocked(fdp, fd, &rights, &fp2, NULL); + error = fget_unlocked(fdp, fd, &cap_no_rights, &fp2, NULL); if (error != 0) { fdrop(fp, td); break; @@ -729,8 +723,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) break; case F_GETLK: - error = fget_unlocked(fdp, fd, - cap_rights_init(&rights, CAP_FLOCK), &fp, NULL); + error = fget_unlocked(fdp, fd, &cap_flock_rights, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -767,8 +760,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) arg = arg ? 128 * 1024: 0; /* FALLTHROUGH */ case F_READAHEAD: - error = fget_unlocked(fdp, fd, - cap_rights_init(&rights), &fp, NULL); + error = fget_unlocked(fdp, fd, &cap_no_rights, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -1363,12 +1355,11 @@ int kern_fstat(struct thread *td, int fd, struct stat *sbp) { struct file *fp; - cap_rights_t rights; int error; AUDIT_ARG_FD(fd); - error = fget(td, fd, cap_rights_init(&rights, CAP_FSTAT), &fp); + error = fget(td, fd, &cap_fstat_rights, &fp); if (error != 0) return (error); @@ -1445,10 +1436,9 @@ kern_fpathconf(struct thread *td, int fd, int name, long *valuep) { struct file *fp; struct vnode *vp; - cap_rights_t rights; int error; - error = fget(td, fd, cap_rights_init(&rights, CAP_FPATHCONF), &fp); + error = fget(td, fd, &cap_fpathconf_rights, &fp); if (error != 0) return (error); @@ -2982,10 +2972,9 @@ sys_flock(struct thread *td, struct flock_args *uap) struct file *fp; struct vnode *vp; struct flock lf; - cap_rights_t rights; int error; - error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FLOCK), &fp); + error = fget(td, uap->fd, &cap_flock_rights, &fp); if (error != 0) return (error); if (fp->f_type != DTYPE_VNODE) { @@ -3633,7 +3622,7 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, #ifdef CAPABILITIES rights = *cap_rights(fdp, i); #else /* !CAPABILITIES */ - cap_rights_init(&rights); + rights = cap_no_rights; #endif /* * Create sysctl entry. It is OK to drop the filedesc diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 9d7740d0e793..6fe100c1ac93 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1286,7 +1286,6 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa struct file *fp; struct knote *kn, *tkn; struct knlist *knl; - cap_rights_t rights; int error, filt, event; int haskqglobal, filedesc_unlock; @@ -1322,8 +1321,7 @@ findkn: if (kev->ident > INT_MAX) error = EBADF; else - error = fget(td, kev->ident, - cap_rights_init(&rights, CAP_EVENT), &fp); + error = fget(td, kev->ident, &cap_event_rights, &fp); if (error) goto done; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 8bd9298a7e0c..9fba7b3426ef 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -374,7 +374,6 @@ do_execve(struct thread *td, struct image_args *args, struct mac *mac_p) struct ucred *tracecred = NULL; #endif struct vnode *oldtextvp = NULL, *newtextvp; - cap_rights_t rights; int credential_changing; int textset; #ifdef MAC @@ -455,8 +454,7 @@ interpret: /* * Descriptors opened only with O_EXEC or O_RDONLY are allowed. */ - error = fgetvp_exec(td, args->fd, - cap_rights_init(&rights, CAP_FEXECVE), &newtextvp); + error = fgetvp_exec(td, args->fd, &cap_fexecve_rights, &newtextvp); if (error) goto exec_fail; vn_lock(newtextvp, LK_EXCLUSIVE | LK_RETRY); diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c index d27dae25b25c..8f7e496d7e46 100644 --- a/sys/kern/kern_sendfile.c +++ b/sys/kern/kern_sendfile.c @@ -511,7 +511,6 @@ static int sendfile_getsock(struct thread *td, int s, struct file **sock_fp, struct socket **so) { - cap_rights_t rights; int error; *sock_fp = NULL; @@ -520,7 +519,7 @@ sendfile_getsock(struct thread *td, int s, struct file **sock_fp, /* * The socket must be a stream socket and connected. */ - error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SEND), + error = getsock_cap(td, s, &cap_send_rights, sock_fp, NULL, NULL); if (error != 0) return (error); @@ -949,7 +948,6 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat) struct sf_hdtr hdtr; struct uio *hdr_uio, *trl_uio; struct file *fp; - cap_rights_t rights; off_t sbytes; int error; @@ -1000,10 +998,8 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat) * sendfile(2) can start at any offset within a file so we require * CAP_READ+CAP_SEEK = CAP_PREAD. */ - if ((error = fget_read(td, uap->fd, - cap_rights_init(&rights, CAP_PREAD), &fp)) != 0) { + if ((error = fget_read(td, uap->fd, &cap_pread_rights, &fp)) != 0) goto out; - } error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset, uap->nbytes, &sbytes, uap->flags, td); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 6e2f57deebe0..24f8dec88fb9 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1789,7 +1789,6 @@ int sys_pdkill(struct thread *td, struct pdkill_args *uap) { struct proc *p; - cap_rights_t rights; int error; AUDIT_ARG_SIGNUM(uap->signum); @@ -1797,8 +1796,7 @@ sys_pdkill(struct thread *td, struct pdkill_args *uap) if ((u_int)uap->signum > _SIG_MAXSIG) return (EINVAL); - error = procdesc_find(td, uap->fd, - cap_rights_init(&rights, CAP_PDKILL), &p); + error = procdesc_find(td, uap->fd, &cap_pdkill_rights, &p); if (error) return (error); AUDIT_ARG_PROCESS(p); diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c index 4e07cca23519..2e0b48b44423 100644 --- a/sys/kern/subr_capability.c +++ b/sys/kern/subr_capability.c @@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$"); #ifdef _KERNEL #include - +#include #include #else /* !_KERNEL */ #include @@ -53,6 +53,38 @@ __FBSDID("$FreeBSD$"); #ifdef _KERNEL #define assert(exp) KASSERT((exp), ("%s:%u", __func__, __LINE__)) + +CAP_RIGHTS_DEFINE1(cap_accept_rights, CAP_ACCEPT); +CAP_RIGHTS_DEFINE1(cap_bind_rights, CAP_BIND); +CAP_RIGHTS_DEFINE1(cap_connect_rights, CAP_CONNECT); +CAP_RIGHTS_DEFINE1(cap_event_rights, CAP_EVENT); +CAP_RIGHTS_DEFINE1(cap_fchdir_rights, CAP_FCHDIR); +CAP_RIGHTS_DEFINE1(cap_fcntl_rights, CAP_FCNTL); +CAP_RIGHTS_DEFINE1(cap_fexecve_rights, CAP_FEXECVE); +CAP_RIGHTS_DEFINE1(cap_flock_rights, CAP_FLOCK); +CAP_RIGHTS_DEFINE1(cap_fpathconf_rights, CAP_FPATHCONF); +CAP_RIGHTS_DEFINE1(cap_fstat_rights, CAP_FSTAT); +CAP_RIGHTS_DEFINE1(cap_fsync_rights, CAP_FSYNC); +CAP_RIGHTS_DEFINE1(cap_ftruncate_rights, CAP_FTRUNCATE); +CAP_RIGHTS_DEFINE1(cap_getpeername_rights, CAP_GETPEERNAME); +CAP_RIGHTS_DEFINE1(cap_getsockname_rights, CAP_GETSOCKNAME); +CAP_RIGHTS_DEFINE1(cap_getsockopt_rights, CAP_GETSOCKOPT); +CAP_RIGHTS_DEFINE1(cap_ioctl_rights, CAP_IOCTL); +CAP_RIGHTS_DEFINE1(cap_listen_rights, CAP_LISTEN); +CAP_RIGHTS_DEFINE1(cap_mmap_rights, CAP_MMAP); +CAP_RIGHTS_DEFINE1(cap_pdgetpid_rights, CAP_PDGETPID); +CAP_RIGHTS_DEFINE1(cap_pdkill_rights, CAP_PDKILL); +CAP_RIGHTS_DEFINE1(cap_pread_rights, CAP_PREAD); +CAP_RIGHTS_DEFINE1(cap_pwrite_rights, CAP_PWRITE); +CAP_RIGHTS_DEFINE1(cap_read_rights, CAP_READ); +CAP_RIGHTS_DEFINE1(cap_recv_rights, CAP_RECV); +CAP_RIGHTS_DEFINE1(cap_send_rights, CAP_SEND); +CAP_RIGHTS_DEFINE1(cap_setsockopt_rights, CAP_SETSOCKOPT); +CAP_RIGHTS_DEFINE1(cap_shutdown_rights, CAP_SHUTDOWN); +CAP_RIGHTS_DEFINE1(cap_write_rights, CAP_WRITE); + +__read_mostly cap_rights_t cap_no_rights; +CAP_RIGHTS_SYSINIT0(cap_no_rights, cap_no_rights); #endif #define CAPARSIZE_MIN (CAP_RIGHTS_VERSION_00 + 2) @@ -149,6 +181,16 @@ cap_rights_is_vset(const cap_rights_t *rights, va_list ap) return (true); } +void +__cap_rights_sysinit(void *arg) +{ + struct cap_rights_init_args *cria = arg; + cap_rights_t *rights = cria->cria_rights; + + __cap_rights_init(CAP_RIGHTS_VERSION, rights, cria->cria_value1, + cria->cria_value2, cria->cria_value3, cria->cria_value4, 0ULL); +} + cap_rights_t * __cap_rights_init(int version, cap_rights_t *rights, ...) { diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 9ab1b07dbf3e..5eca40d54b02 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -283,10 +283,9 @@ int kern_readv(struct thread *td, int fd, struct uio *auio) { struct file *fp; - cap_rights_t rights; int error; - error = fget_read(td, fd, cap_rights_init(&rights, CAP_READ), &fp); + error = fget_read(td, fd, &cap_read_rights, &fp); if (error) return (error); error = dofileread(td, fd, fp, auio, (off_t)-1, 0); @@ -327,10 +326,9 @@ kern_preadv(td, fd, auio, offset) off_t offset; { struct file *fp; - cap_rights_t rights; int error; - error = fget_read(td, fd, cap_rights_init(&rights, CAP_PREAD), &fp); + error = fget_read(td, fd, &cap_pread_rights, &fp); if (error) return (error); if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) @@ -498,10 +496,9 @@ int kern_writev(struct thread *td, int fd, struct uio *auio) { struct file *fp; - cap_rights_t rights; int error; - error = fget_write(td, fd, cap_rights_init(&rights, CAP_WRITE), &fp); + error = fget_write(td, fd, &cap_write_rights, &fp); if (error) return (error); error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0); @@ -542,10 +539,9 @@ kern_pwritev(td, fd, auio, offset) off_t offset; { struct file *fp; - cap_rights_t rights; int error; - error = fget_write(td, fd, cap_rights_init(&rights, CAP_PWRITE), &fp); + error = fget_write(td, fd, &cap_pwrite_rights, &fp); if (error) return (error); if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) @@ -625,13 +621,12 @@ kern_ftruncate(td, fd, length) off_t length; { struct file *fp; - cap_rights_t rights; int error; AUDIT_ARG_FD(fd); if (length < 0) return (EINVAL); - error = fget(td, fd, cap_rights_init(&rights, CAP_FTRUNCATE), &fp); + error = fget(td, fd, &cap_ftruncate_rights, &fp); if (error) return (error); AUDIT_ARG_FILE(td->td_proc, fp); @@ -759,9 +754,6 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data) { struct file *fp; struct filedesc *fdp; -#ifndef CAPABILITIES - cap_rights_t rights; -#endif int error, tmp, locked; AUDIT_ARG_FD(fd); @@ -800,7 +792,7 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data) locked = LA_UNLOCKED; } #else - error = fget(td, fd, cap_rights_init(&rights, CAP_IOCTL), &fp); + error = fget(td, fd, &cap_ioctl_rights, &fp); if (error != 0) { fp = NULL; goto out; @@ -1238,11 +1230,8 @@ selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events) static __inline int getselfd_cap(struct filedesc *fdp, int fd, struct file **fpp) { - cap_rights_t rights; - - cap_rights_init(&rights, CAP_EVENT); - return (fget_unlocked(fdp, fd, &rights, fpp, NULL)); + return (fget_unlocked(fdp, fd, &cap_event_rights, fpp, NULL)); } /* @@ -1480,9 +1469,6 @@ pollrescan(struct thread *td) struct filedesc *fdp; struct file *fp; struct pollfd *fd; -#ifdef CAPABILITIES - cap_rights_t rights; -#endif int n; n = 0; @@ -1499,8 +1485,7 @@ pollrescan(struct thread *td) fp = fdp->fd_ofiles[fd->fd].fde_file; #ifdef CAPABILITIES if (fp == NULL || - cap_check(cap_rights(fdp, fd->fd), - cap_rights_init(&rights, CAP_EVENT)) != 0) + cap_check(cap_rights(fdp, fd->fd), &cap_event_rights) != 0) #else if (fp == NULL) #endif @@ -1558,9 +1543,6 @@ pollscan(td, fds, nfd) { struct filedesc *fdp = td->td_proc->p_fd; struct file *fp; -#ifdef CAPABILITIES - cap_rights_t rights; -#endif int i, n = 0; FILEDESC_SLOCK(fdp); @@ -1574,8 +1556,7 @@ pollscan(td, fds, nfd) fp = fdp->fd_ofiles[fds->fd].fde_file; #ifdef CAPABILITIES if (fp == NULL || - cap_check(cap_rights(fdp, fds->fd), - cap_rights_init(&rights, CAP_EVENT)) != 0) + cap_check(cap_rights(fdp, fds->fd), &cap_event_rights) != 0) #else if (fp == NULL) #endif diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c index 174fffc5c666..859a2a4a108e 100644 --- a/sys/kern/sys_procdesc.c +++ b/sys/kern/sys_procdesc.c @@ -209,13 +209,11 @@ out: int sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap) { - cap_rights_t rights; pid_t pid; int error; AUDIT_ARG_FD(uap->fd); - error = kern_pdgetpid(td, uap->fd, - cap_rights_init(&rights, CAP_PDGETPID), &pid); + error = kern_pdgetpid(td, uap->fd, &cap_pdgetpid_rights, &pid); if (error == 0) error = copyout(&pid, uap->pidp, sizeof(pid)); return (error); diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index ab07d80b0f1a..2ad9ebd3a47a 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -2189,9 +2189,8 @@ static __inline int getmq(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { - cap_rights_t rights; - return _getmq(td, fd, cap_rights_init(&rights, CAP_EVENT), fget, + return _getmq(td, fd, &cap_event_rights, fget, fpp, ppn, pmq); } @@ -2199,9 +2198,8 @@ static __inline int getmq_read(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { - cap_rights_t rights; - return _getmq(td, fd, cap_rights_init(&rights, CAP_READ), fget_read, + return _getmq(td, fd, &cap_read_rights, fget_read, fpp, ppn, pmq); } @@ -2209,9 +2207,8 @@ static __inline int getmq_write(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq) { - cap_rights_t rights; - return _getmq(td, fd, cap_rights_init(&rights, CAP_WRITE), fget_write, + return _getmq(td, fd, &cap_write_rights, fget_write, fpp, ppn, pmq); } @@ -2322,9 +2319,6 @@ sys_kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap) static int kern_kmq_notify(struct thread *td, int mqd, struct sigevent *sigev) { -#ifdef CAPABILITIES - cap_rights_t rights; -#endif struct filedesc *fdp; struct proc *p; struct mqueue *mq; @@ -2357,8 +2351,7 @@ again: goto out; } #ifdef CAPABILITIES - error = cap_check(cap_rights(fdp, mqd), - cap_rights_init(&rights, CAP_EVENT)); + error = cap_check(cap_rights(fdp, mqd), &cap_event_rights); if (error) { FILEDESC_SUNLOCK(fdp); goto out; diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c index f2a03f2581b0..f4e36026a90c 100644 --- a/sys/kern/uipc_sem.c +++ b/sys/kern/uipc_sem.c @@ -691,14 +691,13 @@ struct ksem_close_args { int sys_ksem_close(struct thread *td, struct ksem_close_args *uap) { - cap_rights_t rights; struct ksem *ks; struct file *fp; int error; /* No capability rights required to close a semaphore. */ AUDIT_ARG_FD(uap->id); - error = ksem_get(td, uap->id, cap_rights_init(&rights), &fp); + error = ksem_get(td, uap->id, &cap_no_rights, &fp); if (error) return (error); ks = fp->f_data; @@ -917,14 +916,13 @@ struct ksem_destroy_args { int sys_ksem_destroy(struct thread *td, struct ksem_destroy_args *uap) { - cap_rights_t rights; struct file *fp; struct ksem *ks; int error; /* No capability rights required to close a semaphore. */ AUDIT_ARG_FD(uap->id); - error = ksem_get(td, uap->id, cap_rights_init(&rights), &fp); + error = ksem_get(td, uap->id, &cap_no_rights, &fp); if (error) return (error); ks = fp->f_data; diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 2de9ada463c3..9ed75f253ab3 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -184,7 +184,6 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; - cap_rights_t rights; int error; #ifdef CAPABILITY_MODE @@ -194,7 +193,7 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); - error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND), + error = getsock_cap(td, fd, &cap_bind_rights, &fp, NULL, NULL); if (error != 0) return (error); @@ -244,11 +243,10 @@ kern_listen(struct thread *td, int s, int backlog) { struct socket *so; struct file *fp; - cap_rights_t rights; int error; AUDIT_ARG_FD(s); - error = getsock_cap(td, s, cap_rights_init(&rights, CAP_LISTEN), + error = getsock_cap(td, s, &cap_listen_rights, &fp, NULL, NULL); if (error == 0) { so = fp->f_data; @@ -323,7 +321,6 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, struct sockaddr *sa = NULL; struct socket *head, *so; struct filecaps fcaps; - cap_rights_t rights; u_int fflag; pid_t pgid; int error, fd, tmp; @@ -332,7 +329,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name, *name = NULL; AUDIT_ARG_FD(s); - error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT), + error = getsock_cap(td, s, &cap_accept_rights, &headfp, &fflag, &fcaps); if (error != 0) return (error); @@ -485,7 +482,6 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; - cap_rights_t rights; int error, interrupted = 0; #ifdef CAPABILITY_MODE @@ -495,7 +491,7 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); - error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT), + error = getsock_cap(td, fd, &cap_connect_rights, &fp, NULL, NULL); if (error != 0) return (error); @@ -903,7 +899,6 @@ kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, struct file *fp; struct socket *so; struct sockaddr *fromsa = NULL; - cap_rights_t rights; #ifdef KTRACE struct uio *ktruio = NULL; #endif @@ -914,7 +909,7 @@ kern_recvit(struct thread *td, int s, struct msghdr *mp, enum uio_seg fromseg, *controlp = NULL; AUDIT_ARG_FD(s); - error = getsock_cap(td, s, cap_rights_init(&rights, CAP_RECV), + error = getsock_cap(td, s, &cap_recv_rights, &fp, NULL, NULL); if (error != 0) return (error); @@ -1192,11 +1187,10 @@ kern_shutdown(struct thread *td, int s, int how) { struct socket *so; struct file *fp; - cap_rights_t rights; int error; AUDIT_ARG_FD(s); - error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SHUTDOWN), + error = getsock_cap(td, s, &cap_shutdown_rights, &fp, NULL, NULL); if (error == 0) { so = fp->f_data; @@ -1230,7 +1224,6 @@ kern_setsockopt(struct thread *td, int s, int level, int name, void *val, struct socket *so; struct file *fp; struct sockopt sopt; - cap_rights_t rights; int error; if (val == NULL && valsize != 0) @@ -1255,7 +1248,7 @@ kern_setsockopt(struct thread *td, int s, int level, int name, void *val, } AUDIT_ARG_FD(s); - error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SETSOCKOPT), + error = getsock_cap(td, s, &cap_setsockopt_rights, &fp, NULL, NULL); if (error == 0) { so = fp->f_data; @@ -1296,7 +1289,6 @@ kern_getsockopt(struct thread *td, int s, int level, int name, void *val, struct socket *so; struct file *fp; struct sockopt sopt; - cap_rights_t rights; int error; if (val == NULL) @@ -1321,7 +1313,7 @@ kern_getsockopt(struct thread *td, int s, int level, int name, void *val, } AUDIT_ARG_FD(s); - error = getsock_cap(td, s, cap_rights_init(&rights, CAP_GETSOCKOPT), + error = getsock_cap(td, s, &cap_getsockopt_rights, &fp, NULL, NULL); if (error == 0) { so = fp->f_data; @@ -1369,12 +1361,11 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa, { struct socket *so; struct file *fp; - cap_rights_t rights; socklen_t len; int error; AUDIT_ARG_FD(fd); - error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETSOCKNAME), + error = getsock_cap(td, fd, &cap_getsockname_rights, &fp, NULL, NULL); if (error != 0) return (error); @@ -1456,12 +1447,11 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa, { struct socket *so; struct file *fp; - cap_rights_t rights; socklen_t len; int error; AUDIT_ARG_FD(fd); - error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETPEERNAME), + error = getsock_cap(td, fd, &cap_getpeername_rights, &fp, NULL, NULL); if (error != 0) return (error); diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index c82823f00274..69dd50cf7bdf 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -1450,7 +1450,6 @@ aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, int type, struct aiocb_ops *ops) { struct proc *p = td->td_proc; - cap_rights_t rights; struct file *fp; struct kaiocb *job; struct kaioinfo *ki; @@ -1528,21 +1527,19 @@ aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj, fd = job->uaiocb.aio_fildes; switch (opcode) { case LIO_WRITE: - error = fget_write(td, fd, - cap_rights_init(&rights, CAP_PWRITE), &fp); + error = fget_write(td, fd, &cap_pwrite_rights, &fp); break; case LIO_READ: - error = fget_read(td, fd, - cap_rights_init(&rights, CAP_PREAD), &fp); + error = fget_read(td, fd, &cap_pread_rights, &fp); break; case LIO_SYNC: - error = fget(td, fd, cap_rights_init(&rights, CAP_FSYNC), &fp); + error = fget(td, fd, &cap_fsync_rights, &fp); break; case LIO_MLOCK: fp = NULL; break; case LIO_NOP: - error = fget(td, fd, cap_rights_init(&rights), &fp); + error = fget(td, fd, &cap_no_rights, &fp); break; default: error = EINVAL; @@ -1959,14 +1956,13 @@ sys_aio_cancel(struct thread *td, struct aio_cancel_args *uap) struct kaioinfo *ki; struct kaiocb *job, *jobn; struct file *fp; - cap_rights_t rights; int error; int cancelled = 0; int notcancelled = 0; struct vnode *vp; /* Lookup file object. */ - error = fget(td, uap->fd, cap_rights_init(&rights), &fp); + error = fget(td, uap->fd, &cap_no_rights, &fp); if (error) return (error); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 861a7033b880..ca1b2479ef1a 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -828,11 +828,10 @@ sys_fchdir(struct thread *td, struct fchdir_args *uap) struct vnode *vp, *tdp; struct mount *mp; struct file *fp; - cap_rights_t rights; int error; AUDIT_ARG_FD(uap->fd); - error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_FCHDIR), + error = getvnode(td, uap->fd, &cap_fchdir_rights, &fp); if (error != 0) return (error); @@ -2260,7 +2259,6 @@ kern_statat(struct thread *td, int flag, int fd, char *path, { struct nameidata nd; struct stat sb; - cap_rights_t rights; int error; if (flag & ~AT_SYMLINK_NOFOLLOW) @@ -2268,7 +2266,7 @@ kern_statat(struct thread *td, int flag, int fd, char *path, NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd, - cap_rights_init(&rights, CAP_FSTAT), td); + &cap_fstat_rights, td); if ((error = namei(&nd)) != 0) return (error); @@ -3942,7 +3940,6 @@ kern_getdirentries(struct thread *td, int fd, char *buf, size_t count, struct file *fp; struct uio auio; struct iovec aiov; - cap_rights_t rights; off_t loff; int error, eofflag; off_t foffset; @@ -3951,7 +3948,7 @@ kern_getdirentries(struct thread *td, int fd, char *buf, size_t count, if (count > IOSIZE_MAX) return (EINVAL); auio.uio_resid = count; - error = getvnode(td, fd, cap_rights_init(&rights, CAP_READ), &fp); + error = getvnode(td, fd, &cap_read_rights, &fp); if (error != 0) return (error); if ((fp->f_flag & FREAD) == 0) { @@ -4392,7 +4389,6 @@ kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len) struct file *fp; struct mount *mp; struct vnode *vp; - cap_rights_t rights; off_t olen, ooffset; int error; #ifdef AUDIT @@ -4406,7 +4402,7 @@ kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len) if (offset > OFF_MAX - len) return (EFBIG); AUDIT_ARG_FD(fd); - error = fget(td, fd, cap_rights_init(&rights, CAP_PWRITE), &fp); + error = fget(td, fd, &cap_pwrite_rights, &fp); if (error != 0) return (error); AUDIT_ARG_FILE(td->td_proc, fp); @@ -4493,7 +4489,6 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, struct fadvise_info *fa, *new; struct file *fp; struct vnode *vp; - cap_rights_t rights; off_t end; int error; @@ -4516,7 +4511,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len, } /* XXX: CAP_POSIX_FADVISE? */ AUDIT_ARG_FD(fd); - error = fget(td, fd, cap_rights_init(&rights), &fp); + error = fget(td, fd, &cap_no_rights, &fp); if (error != 0) goto out; AUDIT_ARG_FILE(td->td_proc, fp); diff --git a/sys/netsmb/smb_dev.c b/sys/netsmb/smb_dev.c index 71c9432328bc..f88d14330c4a 100644 --- a/sys/netsmb/smb_dev.c +++ b/sys/netsmb/smb_dev.c @@ -380,7 +380,6 @@ int smb_dev2share(int fd, int mode, struct smb_cred *scred, struct smb_share **sspp, struct smb_dev **ssdp) { - cap_rights_t rights; struct file *fp, *fptmp; struct smb_dev *sdp; struct smb_share *ssp; @@ -388,7 +387,7 @@ smb_dev2share(int fd, int mode, struct smb_cred *scred, int error; td = curthread; - error = fget(td, fd, cap_rights_init(&rights, CAP_READ), &fp); + error = fget(td, fd, &cap_read_rights, &fp); if (error) return (error); fptmp = td->td_fpop; diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h index 4fd496b19a66..80b5e98e33f4 100644 --- a/sys/sys/capsicum.h +++ b/sys/sys/capsicum.h @@ -338,12 +338,99 @@ bool cap_rights_is_valid(const cap_rights_t *rights); cap_rights_t *cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src); cap_rights_t *cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src); bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little); +void __cap_rights_sysinit(void *arg); __END_DECLS +struct cap_rights_init_args { + cap_rights_t *cria_rights; + uint64_t cria_value1; + uint64_t cria_value2; + uint64_t cria_value3; + uint64_t cria_value4; + uint64_t cria_value5; +}; + +#define CAP_RIGHTS_SYSINIT0(name, rights) \ + static struct cap_rights_init_args name##_args = { \ + &(rights) \ + }; \ + SYSINIT(name##_cap_rights_sysinit, SI_SUB_COPYRIGHT+1, SI_ORDER_ANY, \ + __cap_rights_sysinit, &name##_args); + +#define CAP_RIGHTS_SYSINIT1(name, rights, value1) \ + static struct cap_rights_init_args name##_args = { \ + &(rights), \ + (value1) \ + }; \ + SYSINIT(name##_cap_rights_sysinit, SI_SUB_COPYRIGHT+1, SI_ORDER_ANY, \ + __cap_rights_sysinit, &name##_args); + +#define CAP_RIGHTS_SYSINIT2(name, rights, value1, value2) \ + static struct cap_rights_init_args name##_args = { \ + &(rights), \ + (value1), \ + (value2) \ + }; \ + SYSINIT(name##_cap_rights_sysinit, SI_SUB_COPYRIGHT, SI_ORDER_ANY, \ + __cap_rights_sysinit, &name##_args); + +#define CAP_RIGHTS_SYSINIT3(name, rights, value1, value2, value3) \ + static struct cap_rights_init_args name##_args = { \ + &(rights), \ + (value1), \ + (value2), \ + (value3) \ + }; \ + SYSINIT(name##_cap_rights_sysinit, SI_SUB_COPYRIGHT, SI_ORDER_ANY, \ + __cap_rights_sysinit, &name##_args); + +#define CAP_RIGHTS_SYSINIT4(name, rights, value1, value2, value3, value4) \ + static struct cap_rights_init_args name##_args = { \ + &(rights), \ + (value1), \ + (value2), \ + (value3), \ + (value4) \ + }; \ + SYSINIT(name##_cap_rights_sysinit, SI_SUB_COPYRIGHT, SI_ORDER_ANY, \ + __cap_rights_sysinit, &name##_args); + +#define CAP_RIGHTS_DEFINE1(name, value) \ + __read_mostly cap_rights_t name; \ + CAP_RIGHTS_SYSINIT1(name, name, value); #ifdef _KERNEL #include +extern cap_rights_t cap_accept_rights; +extern cap_rights_t cap_bind_rights; +extern cap_rights_t cap_connect_rights; +extern cap_rights_t cap_event_rights; +extern cap_rights_t cap_fchdir_rights; +extern cap_rights_t cap_fcntl_rights; +extern cap_rights_t cap_fexecve_rights; +extern cap_rights_t cap_flock_rights; +extern cap_rights_t cap_fpathconf_rights; +extern cap_rights_t cap_fstat_rights; +extern cap_rights_t cap_ftruncate_rights; +extern cap_rights_t cap_getpeername_rights; +extern cap_rights_t cap_getsockopt_rights; +extern cap_rights_t cap_getsockname_rights; +extern cap_rights_t cap_ioctl_rights; +extern cap_rights_t cap_listen_rights; +extern cap_rights_t cap_mmap_rights; +extern cap_rights_t cap_no_rights; +extern cap_rights_t cap_fsync_rights; +extern cap_rights_t cap_pdgetpid_rights; +extern cap_rights_t cap_pdkill_rights; +extern cap_rights_t cap_pread_rights; +extern cap_rights_t cap_pwrite_rights; +extern cap_rights_t cap_read_rights; +extern cap_rights_t cap_recv_rights; +extern cap_rights_t cap_send_rights; +extern cap_rights_t cap_setsockopt_rights; +extern cap_rights_t cap_shutdown_rights; +extern cap_rights_t cap_write_rights; #define IN_CAPABILITY_MODE(td) (((td)->td_ucred->cr_flags & CRED_FLAG_CAPMODE) != 0) -- cgit v1.2.3