Use the fdeget_locked function instead of the fget_locked in the

sys_capability.

Reviewed by:	pjd@ (earlier version)
Discussed with:	mjg@
This commit is contained in:
Mariusz Zaborski 2018-02-18 15:27:24 +00:00
parent ead15282ae
commit 20641651ec

View File

@ -205,10 +205,10 @@ cap_rights_to_vmprot(cap_rights_t *havep)
*/ */
cap_rights_t * cap_rights_t *
cap_rights_fde(struct filedescent *fde) cap_rights_fde(struct filedescent *fdep)
{ {
return (&fde->fde_rights); return (&fdep->fde_rights);
} }
cap_rights_t * cap_rights_t *
@ -222,24 +222,26 @@ int
kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights) kern_cap_rights_limit(struct thread *td, int fd, cap_rights_t *rights)
{ {
struct filedesc *fdp; struct filedesc *fdp;
struct filedescent *fdep;
int error; int error;
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
FILEDESC_XLOCK(fdp); FILEDESC_XLOCK(fdp);
if (fget_locked(fdp, fd) == NULL) { fdep = fdeget_locked(fdp, fd);
if (fdep == NULL) {
FILEDESC_XUNLOCK(fdp); FILEDESC_XUNLOCK(fdp);
return (EBADF); return (EBADF);
} }
error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE); error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
if (error == 0) { if (error == 0) {
fdp->fd_ofiles[fd].fde_rights = *rights; fdep->fde_rights = *rights;
if (!cap_rights_is_set(rights, CAP_IOCTL)) { if (!cap_rights_is_set(rights, CAP_IOCTL)) {
free(fdp->fd_ofiles[fd].fde_ioctls, M_FILECAPS); free(fdep->fde_ioctls, M_FILECAPS);
fdp->fd_ofiles[fd].fde_ioctls = NULL; fdep->fde_ioctls = NULL;
fdp->fd_ofiles[fd].fde_nioctls = 0; fdep->fde_nioctls = 0;
} }
if (!cap_rights_is_set(rights, CAP_FCNTL)) if (!cap_rights_is_set(rights, CAP_FCNTL))
fdp->fd_ofiles[fd].fde_fcntls = 0; fdep->fde_fcntls = 0;
} }
FILEDESC_XUNLOCK(fdp); FILEDESC_XUNLOCK(fdp);
return (error); return (error);
@ -341,19 +343,23 @@ sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
int int
cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd) cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd)
{ {
struct filedescent *fdep;
u_long *cmds; u_long *cmds;
ssize_t ncmds; ssize_t ncmds;
long i; long i;
FILEDESC_LOCK_ASSERT(fdp);
KASSERT(fd >= 0 && fd < fdp->fd_nfiles, KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
("%s: invalid fd=%d", __func__, fd));
fdep = fdeget_locked(fdp, fd);
KASSERT(fdep == NULL,
("%s: invalid fd=%d", __func__, fd)); ("%s: invalid fd=%d", __func__, fd));
ncmds = fdp->fd_ofiles[fd].fde_nioctls; ncmds = fdep->fde_nioctls;
if (ncmds == -1) if (ncmds == -1)
return (0); return (0);
cmds = fdp->fd_ofiles[fd].fde_ioctls; cmds = fdep->fde_ioctls;
for (i = 0; i < ncmds; i++) { for (i = 0; i < ncmds; i++) {
if (cmds[i] == cmd) if (cmds[i] == cmd)
return (0); return (0);
@ -366,7 +372,7 @@ cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd)
* Check if the current ioctls list can be replaced by the new one. * Check if the current ioctls list can be replaced by the new one.
*/ */
static int static int
cap_ioctl_limit_check(struct filedesc *fdp, int fd, const u_long *cmds, cap_ioctl_limit_check(struct filedescent *fdep, const u_long *cmds,
size_t ncmds) size_t ncmds)
{ {
u_long *ocmds; u_long *ocmds;
@ -374,13 +380,13 @@ cap_ioctl_limit_check(struct filedesc *fdp, int fd, const u_long *cmds,
u_long i; u_long i;
long j; long j;
oncmds = fdp->fd_ofiles[fd].fde_nioctls; oncmds = fdep->fde_nioctls;
if (oncmds == -1) if (oncmds == -1)
return (0); return (0);
if (oncmds < (ssize_t)ncmds) if (oncmds < (ssize_t)ncmds)
return (ENOTCAPABLE); return (ENOTCAPABLE);
ocmds = fdp->fd_ofiles[fd].fde_ioctls; ocmds = fdep->fde_ioctls;
for (i = 0; i < ncmds; i++) { for (i = 0; i < ncmds; i++) {
for (j = 0; j < oncmds; j++) { for (j = 0; j < oncmds; j++) {
if (cmds[i] == ocmds[j]) if (cmds[i] == ocmds[j])
@ -397,6 +403,7 @@ int
kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds) kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds)
{ {
struct filedesc *fdp; struct filedesc *fdp;
struct filedescent *fdep;
u_long *ocmds; u_long *ocmds;
int error; int error;
@ -410,18 +417,19 @@ kern_cap_ioctls_limit(struct thread *td, int fd, u_long *cmds, size_t ncmds)
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
FILEDESC_XLOCK(fdp); FILEDESC_XLOCK(fdp);
if (fget_locked(fdp, fd) == NULL) { fdep = fdeget_locked(fdp, fd);
if (fdep == NULL) {
error = EBADF; error = EBADF;
goto out; goto out;
} }
error = cap_ioctl_limit_check(fdp, fd, cmds, ncmds); error = cap_ioctl_limit_check(fdep, cmds, ncmds);
if (error != 0) if (error != 0)
goto out; goto out;
ocmds = fdp->fd_ofiles[fd].fde_ioctls; ocmds = fdep->fde_ioctls;
fdp->fd_ofiles[fd].fde_ioctls = cmds; fdep->fde_ioctls = cmds;
fdp->fd_ofiles[fd].fde_nioctls = ncmds; fdep->fde_nioctls = ncmds;
cmds = ocmds; cmds = ocmds;
error = 0; error = 0;
@ -523,7 +531,7 @@ out:
* Test whether a capability grants the given fcntl command. * Test whether a capability grants the given fcntl command.
*/ */
int int
cap_fcntl_check_fde(struct filedescent *fde, int cmd) cap_fcntl_check_fde(struct filedescent *fdep, int cmd)
{ {
uint32_t fcntlcap; uint32_t fcntlcap;
@ -531,7 +539,7 @@ cap_fcntl_check_fde(struct filedescent *fde, int cmd)
KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0, KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0,
("Unsupported fcntl=%d.", cmd)); ("Unsupported fcntl=%d.", cmd));
if ((fde->fde_fcntls & fcntlcap) != 0) if ((fdep->fde_fcntls & fcntlcap) != 0)
return (0); return (0);
return (ENOTCAPABLE); return (ENOTCAPABLE);
@ -551,6 +559,7 @@ int
sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap) sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
{ {
struct filedesc *fdp; struct filedesc *fdp;
struct filedescent *fdep;
uint32_t fcntlrights; uint32_t fcntlrights;
int fd; int fd;
@ -566,17 +575,18 @@ sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
FILEDESC_XLOCK(fdp); FILEDESC_XLOCK(fdp);
if (fget_locked(fdp, fd) == NULL) { fdep = fdeget_locked(fdp, fd);
if (fdep == NULL) {
FILEDESC_XUNLOCK(fdp); FILEDESC_XUNLOCK(fdp);
return (EBADF); return (EBADF);
} }
if ((fcntlrights & ~fdp->fd_ofiles[fd].fde_fcntls) != 0) { if ((fcntlrights & ~fdep->fde_fcntls) != 0) {
FILEDESC_XUNLOCK(fdp); FILEDESC_XUNLOCK(fdp);
return (ENOTCAPABLE); return (ENOTCAPABLE);
} }
fdp->fd_ofiles[fd].fde_fcntls = fcntlrights; fdep->fde_fcntls = fcntlrights;
FILEDESC_XUNLOCK(fdp); FILEDESC_XUNLOCK(fdp);
return (0); return (0);
@ -586,6 +596,7 @@ int
sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap) sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
{ {
struct filedesc *fdp; struct filedesc *fdp;
struct filedescent *fdep;
uint32_t rights; uint32_t rights;
int fd; int fd;
@ -595,11 +606,12 @@ sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
fdp = td->td_proc->p_fd; fdp = td->td_proc->p_fd;
FILEDESC_SLOCK(fdp); FILEDESC_SLOCK(fdp);
if (fget_locked(fdp, fd) == NULL) { fdep = fdeget_locked(fdp, fd);
if (fdep == NULL) {
FILEDESC_SUNLOCK(fdp); FILEDESC_SUNLOCK(fdp);
return (EBADF); return (EBADF);
} }
rights = fdp->fd_ofiles[fd].fde_fcntls; rights = fdep->fde_fcntls;
FILEDESC_SUNLOCK(fdp); FILEDESC_SUNLOCK(fdp);
return (copyout(&rights, uap->fcntlrightsp, sizeof(rights))); return (copyout(&rights, uap->fcntlrightsp, sizeof(rights)));