Prepare fget_unlocked for reading fd table only once.

Some capsicum functions accept fdp + fd and lookup fde based on that.
Add variants which accept fde.

Reviewed by:	pjd
MFC after:	1 week
This commit is contained in:
Mateusz Guzik 2014-07-23 19:33:49 +00:00
parent b679017609
commit a1bf811596
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=269023
3 changed files with 34 additions and 8 deletions

View File

@ -2301,6 +2301,9 @@ int
fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
int needfcntl, struct file **fpp, cap_rights_t *haverightsp)
{
#ifdef CAPABILITIES
struct filedescent fde;
#endif
struct file *fp;
u_int count;
#ifdef CAPABILITIES
@ -2323,17 +2326,22 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
* due to preemption.
*/
for (;;) {
#ifdef CAPABILITIES
fde = fdp->fd_ofiles[fd];
fp = fde.fde_file;
#else
fp = fdp->fd_ofiles[fd].fde_file;
#endif
if (fp == NULL)
return (EBADF);
#ifdef CAPABILITIES
haverights = *cap_rights(fdp, fd);
haverights = *cap_rights_fde(&fde);
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);
error = cap_fcntl_check_fde(&fde, needfcntl);
if (error != 0)
return (error);
}

View File

@ -199,11 +199,19 @@ cap_rights_to_vmprot(cap_rights_t *havep)
* any other way, as we want to keep all capability permission evaluation in
* this one file.
*/
cap_rights_t *
cap_rights_fde(struct filedescent *fde)
{
return (&fde->fde_rights);
}
cap_rights_t *
cap_rights(struct filedesc *fdp, int fd)
{
return (&fdp->fd_ofiles[fd].fde_rights);
return (cap_rights_fde(&fdp->fd_ofiles[fd]));
}
/*
@ -486,23 +494,30 @@ sys_cap_ioctls_get(struct thread *td, struct cap_ioctls_get_args *uap)
* Test whether a capability grants the given fcntl command.
*/
int
cap_fcntl_check(struct filedesc *fdp, int fd, int cmd)
cap_fcntl_check_fde(struct filedescent *fde, int cmd)
{
uint32_t fcntlcap;
KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
("%s: invalid fd=%d", __func__, fd));
fcntlcap = (1 << cmd);
KASSERT((CAP_FCNTL_ALL & fcntlcap) != 0,
("Unsupported fcntl=%d.", cmd));
if ((fdp->fd_ofiles[fd].fde_fcntls & fcntlcap) != 0)
if ((fde->fde_fcntls & fcntlcap) != 0)
return (0);
return (ENOTCAPABLE);
}
int
cap_fcntl_check(struct filedesc *fdp, int fd, int cmd)
{
KASSERT(fd >= 0 && fd < fdp->fd_nfiles,
("%s: invalid fd=%d", __func__, fd));
return (cap_fcntl_check_fde(&fdp->fd_ofiles[fd], cmd));
}
int
sys_cap_fcntls_limit(struct thread *td, struct cap_fcntls_limit_args *uap)
{

View File

@ -341,6 +341,7 @@ __END_DECLS
#define IN_CAPABILITY_MODE(td) (((td)->td_ucred->cr_flags & CRED_FLAG_CAPMODE) != 0)
struct filedesc;
struct filedescent;
/*
* Test whether a capability grants the requested rights.
@ -355,9 +356,11 @@ u_char cap_rights_to_vmprot(cap_rights_t *havep);
* For the purposes of procstat(1) and similar tools, allow kern_descrip.c to
* extract the rights from a capability.
*/
cap_rights_t *cap_rights_fde(struct filedescent *fde);
cap_rights_t *cap_rights(struct filedesc *fdp, int fd);
int cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd);
int cap_fcntl_check_fde(struct filedescent *fde, int cmd);
int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd);
#else /* !_KERNEL */