Handle cases where capability rights are not provided.

Reported by:	kib
This commit is contained in:
pjd 2013-09-05 11:58:12 +00:00
parent 12cfeea19a
commit 1c7defb76e
6 changed files with 42 additions and 22 deletions

View File

@ -54,7 +54,7 @@ releasef(int fd)
struct file *fp; struct file *fp;
/* No CAP_ rights required, as we're only releasing. */ /* 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);
fdrop(fp, curthread); fdrop(fp, curthread);
} }

View File

@ -34,6 +34,9 @@ __FBSDID("$FreeBSD$");
*/ */
#include <sys/param.h> #include <sys/param.h>
#if __FreeBSD_version >= 900000
#include <sys/capability.h>
#endif
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/conf.h> #include <sys/conf.h>
#include <sys/kernel.h> #include <sys/kernel.h>
@ -77,15 +80,19 @@ static int
aacraid_linux_ioctl(struct thread *td, struct linux_ioctl_args *args) aacraid_linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
{ {
struct file *fp; struct file *fp;
#if __FreeBSD_version >= 900000
cap_rights_t rights;
#endif
u_long cmd; u_long cmd;
int error; int error;
if ((error = fget(td, args->fd,
#if __FreeBSD_version >= 900000 #if __FreeBSD_version >= 900000
if ((error = fget(td, args->fd, 0, &fp)) != 0) cap_rights_init(&rights, CAP_IOCTL),
#else
if ((error = fget(td, args->fd, &fp)) != 0)
#endif #endif
&fp)) != 0) {
return (error); return (error);
}
cmd = args->cmd; cmd = args->cmd;
/* /*

View File

@ -309,7 +309,7 @@ fdesc_lookup(ap)
/* /*
* No rights to check since 'fp' isn't actually used. * 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; goto bad;
/* Check if we're looking up ourselves. */ /* Check if we're looking up ourselves. */

View File

@ -586,8 +586,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_SETLK: case F_SETLK:
do_setlk: do_setlk:
error = fget_unlocked(fdp, fd, cap_rights_init(&rights, CAP_FLOCK);
cap_rights_init(&rights, CAP_FLOCK), 0, &fp, NULL); error = fget_unlocked(fdp, fd, &rights, 0, &fp, NULL);
if (error != 0) if (error != 0)
break; break;
if (fp->f_type != DTYPE_VNODE) { 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 * that the closing thread was a bit slower and that the
* advisory lock succeeded before the close. * 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) { if (error != 0) {
fdrop(fp, td); fdrop(fp, td);
break; break;
@ -733,7 +733,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
arg = arg ? 128 * 1024: 0; arg = arg ? 128 * 1024: 0;
/* FALLTHROUGH */ /* FALLTHROUGH */
case F_READAHEAD: case F_READAHEAD:
error = fget_unlocked(fdp, fd, 0, 0, &fp, NULL); error = fget_unlocked(fdp, fd, NULL, 0, &fp, NULL);
if (error != 0) if (error != 0)
break; break;
if (fp->f_type != DTYPE_VNODE) { if (fp->f_type != DTYPE_VNODE) {
@ -2324,13 +2324,15 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
return (EBADF); return (EBADF);
#ifdef CAPABILITIES #ifdef CAPABILITIES
haverights = *cap_rights(fdp, fd); haverights = *cap_rights(fdp, fd);
error = cap_check(&haverights, needrightsp); if (needrightsp != NULL) {
if (error != 0) error = cap_check(&haverights, needrightsp);
return (error);
if (cap_rights_is_set(needrightsp, CAP_FCNTL)) {
error = cap_fcntl_check(fdp, fd, needfcntl);
if (error != 0) if (error != 0)
return (error); return (error);
if (cap_rights_is_set(needrightsp, CAP_FCNTL)) {
error = cap_fcntl_check(fdp, fd, needfcntl);
if (error != 0)
return (error);
}
} }
#endif #endif
count = fp->f_count; count = fp->f_count;
@ -2382,7 +2384,10 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags,
*fpp = NULL; *fpp = NULL;
if (td == NULL || (fdp = td->td_proc->p_fd) == NULL) if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
return (EBADF); return (EBADF);
needrights = *needrightsp; if (needrightsp != NULL)
needrights = *needrightsp;
else
cap_rights_init(&needrights);
if (maxprotp != NULL) if (maxprotp != NULL)
cap_rights_set(&needrights, CAP_MMAP); cap_rights_set(&needrights, CAP_MMAP);
error = fget_unlocked(fdp, fd, &needrights, 0, &fp, &haverights); 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); return (EBADF);
#ifdef CAPABILITIES #ifdef CAPABILITIES
error = cap_check(cap_rights(fdp, fd), needrightsp); if (needrightsp != NULL) {
if (error != 0) error = cap_check(cap_rights(fdp, fd), needrightsp);
return (error); if (error != 0)
return (error);
}
#endif #endif
if (fp->f_vnode == NULL) if (fp->f_vnode == NULL)

View File

@ -47,8 +47,10 @@ linux_fget(unsigned int fd)
{ {
struct file *file; 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 (NULL);
}
return (struct linux_file *)file->f_data; return (struct linux_file *)file->f_data;
} }
@ -70,8 +72,10 @@ put_unused_fd(unsigned int fd)
{ {
struct file *file; 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; return;
}
fdclose(curthread->td_proc->p_fd, file, fd, curthread); 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; 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; file = NULL;
}
filp->_file = file; filp->_file = file;
finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops);
} }

View File

@ -496,7 +496,7 @@ audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
vhold(cvnp); vhold(cvnp);
} else { } else {
/* XXX: fgetvp() that vhold()s vnode instead of vref()ing it would be better */ /* 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) { if (error) {
cpath[0] = '\0'; cpath[0] = '\0';
if (rvnp != NULL) if (rvnp != NULL)