fd: add fget_cap and fget_cap_locked primitives

They can be used to obtain capabilities along with a referenced fp.

Reviewed by:	mjg@
This commit is contained in:
oshogbo 2016-09-12 22:46:19 +00:00
parent 27cffd4f48
commit 30c9f87902
2 changed files with 76 additions and 0 deletions

View File

@ -2445,6 +2445,77 @@ finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops)
atomic_store_rel_ptr((volatile uintptr_t *)&fp->f_ops, (uintptr_t)ops);
}
int
fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp, struct filecaps *havecapsp)
{
struct filedescent *fde;
int error;
FILEDESC_LOCK_ASSERT(fdp);
fde = fdeget_locked(fdp, fd);
if (fde == NULL) {
error = EBADF;
goto out;
}
#ifdef CAPABILITIES
error = cap_check(cap_rights_fde(fde), needrightsp);
if (error != 0)
goto out;
#endif
if (havecapsp != NULL)
filecaps_copy(&fde->fde_caps, havecapsp, true);
fhold(fde->fde_file);
*fpp = fde->fde_file;
error = 0;
out:
return (error);
}
int
fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
struct file **fpp, struct filecaps *havecapsp)
{
struct filedesc *fdp;
struct file *fp;
int error;
seq_t seq;
fdp = td->td_proc->p_fd;
for (;;) {
error = fget_unlocked(fdp, fd, needrightsp, &fp, &seq);
if (error != 0)
return (error);
if (havecapsp != NULL) {
if (!filecaps_copy(&fdp->fd_ofiles[fd].fde_caps,
havecapsp, false)) {
fdrop(fp, td);
goto get_locked;
}
}
if (!fd_modified(fdp, fd, seq))
break;
fdrop(fp, td);
}
*fpp = fp;
return (0);
get_locked:
FILEDESC_SLOCK(fdp);
error = fget_cap_locked(fdp, fd, needrightsp, fpp, havecapsp);
FILEDESC_SUNLOCK(fdp);
return (error);
}
int
fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp, seq_t *seqp)

View File

@ -190,6 +190,11 @@ int getvnode(struct thread *td, int fd, cap_rights_t *rightsp,
struct file **fpp);
void mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
int fget_cap_locked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp, struct filecaps *havecapsp);
int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
struct file **fpp, struct filecaps *havecapsp);
/* Return a referenced file from an unlocked descriptor. */
int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp, seq_t *seqp);