From ab568de78923856b1240c6f3d29b95fde765a5bc Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Thu, 5 Sep 2013 11:58:12 +0000 Subject: [PATCH] Handle cases where capability rights are not provided. Reported by: kib --- sys/cddl/compat/opensolaris/sys/file.h | 2 +- sys/dev/aacraid/aacraid_linux.c | 13 +++++++--- sys/fs/fdescfs/fdesc_vnops.c | 2 +- sys/kern/kern_descrip.c | 33 ++++++++++++++++---------- sys/ofed/include/linux/file.h | 12 +++++++--- sys/security/audit/audit_bsm_klib.c | 2 +- 6 files changed, 42 insertions(+), 22 deletions(-) diff --git a/sys/cddl/compat/opensolaris/sys/file.h b/sys/cddl/compat/opensolaris/sys/file.h index a1c1d4521992..5f83082f23c0 100644 --- a/sys/cddl/compat/opensolaris/sys/file.h +++ b/sys/cddl/compat/opensolaris/sys/file.h @@ -54,7 +54,7 @@ releasef(int fd) struct file *fp; /* No CAP_ rights required, as we're only releasing. */ - if (fget(curthread, fd, 0, &fp) == 0) { + if (fget(curthread, fd, NULL, &fp) == 0) { fdrop(fp, curthread); fdrop(fp, curthread); } diff --git a/sys/dev/aacraid/aacraid_linux.c b/sys/dev/aacraid/aacraid_linux.c index 3d85445fa823..e58d0a47a80a 100644 --- a/sys/dev/aacraid/aacraid_linux.c +++ b/sys/dev/aacraid/aacraid_linux.c @@ -34,6 +34,9 @@ __FBSDID("$FreeBSD$"); */ #include +#if __FreeBSD_version >= 900000 +#include +#endif #include #include #include @@ -77,15 +80,19 @@ static int aacraid_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) { struct file *fp; +#if __FreeBSD_version >= 900000 + cap_rights_t rights; +#endif u_long cmd; int error; + if ((error = fget(td, args->fd, #if __FreeBSD_version >= 900000 - if ((error = fget(td, args->fd, 0, &fp)) != 0) -#else - if ((error = fget(td, args->fd, &fp)) != 0) + cap_rights_init(&rights, CAP_IOCTL), #endif + &fp)) != 0) { return (error); + } cmd = args->cmd; /* diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index fe939b1f6577..b976504353c9 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -309,7 +309,7 @@ fdesc_lookup(ap) /* * No rights to check since 'fp' isn't actually used. */ - if ((error = fget(td, fd, 0, &fp)) != 0) + if ((error = fget(td, fd, NULL, &fp)) != 0) goto bad; /* Check if we're looking up ourselves. */ diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index a0545e10b1e9..9e9010f0f62a 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -586,8 +586,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) case F_SETLK: do_setlk: - error = fget_unlocked(fdp, fd, - cap_rights_init(&rights, CAP_FLOCK), 0, &fp, NULL); + cap_rights_init(&rights, CAP_FLOCK); + error = fget_unlocked(fdp, fd, &rights, 0, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -676,7 +676,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, 0, 0, &fp2, NULL); + error = fget_unlocked(fdp, fd, &rights, 0, &fp2, NULL); if (error != 0) { fdrop(fp, td); break; @@ -733,7 +733,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, 0, 0, &fp, NULL); + error = fget_unlocked(fdp, fd, NULL, 0, &fp, NULL); if (error != 0) break; if (fp->f_type != DTYPE_VNODE) { @@ -2324,13 +2324,15 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp, return (EBADF); #ifdef CAPABILITIES haverights = *cap_rights(fdp, fd); - error = cap_check(&haverights, needrightsp); - if (error != 0) - return (error); - if (cap_rights_is_set(needrightsp, CAP_FCNTL)) { - error = cap_fcntl_check(fdp, fd, needfcntl); + if (needrightsp != NULL) { + error = cap_check(&haverights, needrightsp); if (error != 0) return (error); + if (cap_rights_is_set(needrightsp, CAP_FCNTL)) { + error = cap_fcntl_check(fdp, fd, needfcntl); + if (error != 0) + return (error); + } } #endif count = fp->f_count; @@ -2382,7 +2384,10 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags, *fpp = NULL; if (td == NULL || (fdp = td->td_proc->p_fd) == NULL) return (EBADF); - needrights = *needrightsp; + if (needrightsp != NULL) + needrights = *needrightsp; + else + cap_rights_init(&needrights); if (maxprotp != NULL) cap_rights_set(&needrights, CAP_MMAP); error = fget_unlocked(fdp, fd, &needrights, 0, &fp, &haverights); @@ -2517,9 +2522,11 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp, return (EBADF); #ifdef CAPABILITIES - error = cap_check(cap_rights(fdp, fd), needrightsp); - if (error != 0) - return (error); + if (needrightsp != NULL) { + error = cap_check(cap_rights(fdp, fd), needrightsp); + if (error != 0) + return (error); + } #endif if (fp->f_vnode == NULL) diff --git a/sys/ofed/include/linux/file.h b/sys/ofed/include/linux/file.h index b9bd8b154291..bb9d58d50f8d 100644 --- a/sys/ofed/include/linux/file.h +++ b/sys/ofed/include/linux/file.h @@ -47,8 +47,10 @@ linux_fget(unsigned int fd) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0) + if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, 0, &file, + NULL) != 0) { return (NULL); + } return (struct linux_file *)file->f_data; } @@ -70,8 +72,10 @@ put_unused_fd(unsigned int fd) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0) + if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, 0, &file, + NULL) != 0) { return; + } fdclose(curthread->td_proc->p_fd, file, fd, curthread); } @@ -80,8 +84,10 @@ fd_install(unsigned int fd, struct linux_file *filp) { struct file *file; - if (fget_unlocked(curthread->td_proc->p_fd, fd, 0, 0, &file, NULL) != 0) + if (fget_unlocked(curthread->td_proc->p_fd, fd, NULL, 0, &file, + NULL) != 0) { file = NULL; + } filp->_file = file; finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); } diff --git a/sys/security/audit/audit_bsm_klib.c b/sys/security/audit/audit_bsm_klib.c index 5f5d58bdff28..d06c7705eafd 100644 --- a/sys/security/audit/audit_bsm_klib.c +++ b/sys/security/audit/audit_bsm_klib.c @@ -496,7 +496,7 @@ audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath) vhold(cvnp); } else { /* XXX: fgetvp() that vhold()s vnode instead of vref()ing it would be better */ - error = fgetvp(td, dirfd, 0, &cvnp); + error = fgetvp(td, dirfd, NULL, &cvnp); if (error) { cpath[0] = '\0'; if (rvnp != NULL)