fusefs: send FUSE_OPEN for every open(2) with unique credentials

By default, FUSE performs authorization in the server.  That means that it's
insecure for the client to reuse FUSE file handles between different users,
groups, or processes.  Linux handles this problem by creating a different
FUSE file handle for every file descriptor.  FreeBSD can't, due to
differences in our VFS design.

This commit adds credential information to each fuse_filehandle.  During
open(2), fusefs will now only reuse a file handle if it matches the exact
same access mode, pid, uid, and gid of the calling process.

PR:		236844
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Alan Somers 2019-04-01 20:42:15 +00:00
parent 363a74163b
commit f8d4af104b
9 changed files with 182 additions and 76 deletions

View File

@ -109,11 +109,6 @@ fuse_filehandle_open(struct vnode *vp, fufh_type_t fufh_type,
int oflags = 0;
int op = FUSE_OPEN;
if (fuse_filehandle_valid(vp, fufh_type)) {
panic("FUSE: filehandle_open called despite valid fufh (type=%d)",
fufh_type);
/* NOTREACHED */
}
/*
* Note that this means we are effectively FILTERING OUT open() flags.
*/
@ -140,7 +135,8 @@ fuse_filehandle_open(struct vnode *vp, fufh_type_t fufh_type,
}
foo = fdi.answ;
fuse_filehandle_init(vp, fufh_type, fufhp, foo->fh);
fuse_filehandle_init(vp, fufh_type, fufhp, td->td_proc->p_pid, cred,
foo->fh);
fuse_vnode_open(vp, foo->open_flags, td);
@ -181,37 +177,66 @@ out:
return err;
}
int
fuse_filehandle_valid(struct vnode *vp, fufh_type_t fufh_type)
{
return (0 == fuse_filehandle_get(vp, fufh_type, NULL));
}
/*
* Check for a valid file handle, first the type requested, but if that
* isn't valid, try for FUFH_RDWR.
* Return the FUFH type that is valid or FUFH_INVALID if there are none.
* This is a variant of fuse_filehandle_valid() analogous to
* fuse_filehandle_getrw().
* Return true if there is any file handle with the correct credentials and
* a fufh type that includes the provided one.
* A pid of 0 means "don't care"
*/
fufh_type_t
fuse_filehandle_validrw(struct vnode *vp, fufh_type_t fufh_type)
{
if (fuse_filehandle_get(vp, fufh_type, NULL) == 0)
return (fufh_type);
if (fuse_filehandle_get(vp, FUFH_RDWR, NULL) == 0)
return (FUFH_RDWR);
return (FUFH_INVALID);
}
int
fuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp)
bool
fuse_filehandle_validrw(struct vnode *vp, fufh_type_t fufh_type,
struct ucred *cred, pid_t pid)
{
struct fuse_vnode_data *fvdat = VTOFUD(vp);
struct fuse_filehandle *fufh;
/* TODO: Find a list entry with the same flags, pid, gid, and uid */
/*
* Unlike fuse_filehandle_get, we want to search for a filehandle with
* the exact cred, and no fallback
*/
LIST_FOREACH(fufh, &fvdat->handles, next) {
if (fufh->flags == fufh_type &&
fufh->uid == cred->cr_uid &&
fufh->gid == cred->cr_rgid &&
(pid == 0 || fufh->pid == pid))
return true;
}
if (fufh_type == FUFH_EXEC)
return false;
/* Fallback: find a RDWR list entry with the right cred */
LIST_FOREACH(fufh, &fvdat->handles, next) {
if (fufh->flags == FUFH_RDWR &&
fufh->uid == cred->cr_uid &&
fufh->gid == cred->cr_rgid &&
(pid == 0 || fufh->pid == pid))
return true;
}
return false;
}
int
fuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp, struct ucred *cred, pid_t pid)
{
struct fuse_vnode_data *fvdat = VTOFUD(vp);
struct fuse_filehandle *fufh;
if (cred == NULL)
goto fallback;
LIST_FOREACH(fufh, &fvdat->handles, next) {
if (fufh->flags == fufh_type &&
fufh->uid == cred->cr_uid &&
fufh->gid == cred->cr_rgid &&
(pid == 0 || fufh->pid == pid))
goto found;
}
fallback:
/* Fallback: find a list entry with the right flags */
LIST_FOREACH(fufh, &fvdat->handles, next) {
if (fufh->flags == fufh_type)
@ -220,6 +245,8 @@ fuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type,
if (fufh == NULL)
return EBADF;
found:
if (fufhp != NULL)
*fufhp = fufh;
return 0;
@ -227,19 +254,20 @@ fuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type,
int
fuse_filehandle_getrw(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp)
struct fuse_filehandle **fufhp, struct ucred *cred, pid_t pid)
{
int err;
err = fuse_filehandle_get(vp, fufh_type, fufhp);
err = fuse_filehandle_get(vp, fufh_type, fufhp, cred, pid);
if (err)
err = fuse_filehandle_get(vp, FUFH_RDWR, fufhp);
err = fuse_filehandle_get(vp, FUFH_RDWR, fufhp, cred, pid);
return err;
}
void
fuse_filehandle_init(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp, uint64_t fh_id)
struct fuse_filehandle **fufhp, pid_t pid, struct ucred *cred,
uint64_t fh_id)
{
struct fuse_vnode_data *fvdat = VTOFUD(vp);
struct fuse_filehandle *fufh;
@ -249,7 +277,10 @@ fuse_filehandle_init(struct vnode *vp, fufh_type_t fufh_type,
MPASS(fufh != NULL);
fufh->fh_id = fh_id;
fufh->flags = fufh_type;
/* TODO: initialize fufh credentials and open flags */
fufh->gid = cred->cr_rgid;
fufh->uid = cred->cr_uid;
fufh->pid = pid;
/* TODO: initialize open flags */
if (!FUFH_IS_VALID(fufh)) {
panic("FUSE: init: invalid filehandle id (type=%d)", fufh_type);
}

View File

@ -78,6 +78,56 @@ typedef enum fufh_type {
FUFH_EXEC = O_EXEC,
} fufh_type_t;
/*
* FUSE File Handles
*
* The FUSE protocol says that a server may assign a unique 64-bit file handle
* every time that a file is opened. Effectively, that's once for each file
* descriptor.
*
* Unfortunately, the VFS doesn't help us here. VOPs don't have a
* struct file* argument. fileops do, but many syscalls bypass the fileops
* layer and go straight to a vnode. Some, like writing from cache, can't
* track a file handle even in theory. The entire concept of the file handle
* is a product of FUSE's Linux origins; Linux lacks vnodes and almost every
* file system operation takes a struct file* argument.
*
* Since FreeBSD's VFS is more file descriptor-agnostic, we must store FUSE
* filehandles in the vnode. One option would be to only store a single file
* handle and never open FUSE files concurrently. That's what NetBSD does.
* But that violates FUSE's security model. FUSE expects the server to do all
* authorization (except when mounted with -o default_permissions). In order
* to do that, the server needs us to send FUSE_OPEN every time somebody opens
* a new file descriptor.
*
* Another option would be to never open FUSE files concurrently, but send a
* FUSE_ACCESS prior to every open after the first. That would give the server
* the opportunity to authorize the access. Unfortunately, the FUSE protocol
* makes ACCESS optional. File systems that don't implement it are assumed to
* authorize everything. A survey of 32 fuse file systems showed that only 14
* implemented access. Among the laggards were a few that really ought to be
* doing server-side authorization.
*
* So we do something hacky, similar to what OpenBSD, Illumos, and OSXFuse do.
* we store a list of file handles, one for each combination of vnode, uid,
* gid, pid, and access mode. When opening a file, we first check whether
* there's already a matching file handle. If so, we reuse it. If not, we
* send FUSE_OPEN and create a new file handle. That minimizes the number of
* open file handles while still allowing the server to authorize stuff.
*
* VOPs that need a file handle search through the list for a close match.
* They can't be guaranteed of finding an exact match because, for example, a
* process may have changed its UID since opening the file. Also, most VOPs
* don't know exactly what permission they need. Is O_RDWR required or is
* O_RDONLY good enough? So the file handle we end up using may not be exactly
* the one we're supposed to use with that file descriptor. But if the FUSE
* file system isn't too picky, it will work. (FWIW even Linux sometimes
* guesses the file handle, during writes from cache or most SETATTR
* operations).
*
* I suspect this mess is part of the reason why neither NFS nor 9P have an
* equivalent of FUSE file handles.
*/
struct fuse_filehandle {
LIST_ENTRY(fuse_filehandle) next;
@ -132,15 +182,18 @@ fuse_filehandle_xlate_to_oflags(fufh_type_t type)
return oflags;
}
int fuse_filehandle_valid(struct vnode *vp, fufh_type_t fufh_type);
fufh_type_t fuse_filehandle_validrw(struct vnode *vp, fufh_type_t fufh_type);
bool fuse_filehandle_validrw(struct vnode *vp, fufh_type_t fufh_type,
struct ucred *cred, pid_t pid);
int fuse_filehandle_get(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp);
struct fuse_filehandle **fufhp, struct ucred *cred,
pid_t pid);
int fuse_filehandle_getrw(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp);
struct fuse_filehandle **fufhp, struct ucred *cred,
pid_t pid);
void fuse_filehandle_init(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp, uint64_t fh_id);
struct fuse_filehandle **fufhp, pid_t pid,
struct ucred *cred, uint64_t fh_id);
int fuse_filehandle_open(struct vnode *vp, fufh_type_t fufh_type,
struct fuse_filehandle **fufhp, struct thread *td,
struct ucred *cred);

View File

@ -111,27 +111,28 @@ fuse_read_directbackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh);
static int
fuse_read_biobackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh);
struct ucred *cred, struct fuse_filehandle *fufh, pid_t pid);
static int
fuse_write_directbackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag);
static int
fuse_write_biobackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag);
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag, pid_t pid);
SDT_PROBE_DEFINE5(fuse, , io, io_dispatch, "struct vnode*", "struct uio*",
"int", "struct ucred*", "struct fuse_filehandle*");
int
fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
struct ucred *cred)
struct ucred *cred, pid_t pid)
{
struct fuse_filehandle *fufh;
int err, directio;
fufh_type_t fufh_type;
MPASS(vp->v_type == VREG || vp->v_type == VDIR);
err = fuse_filehandle_getrw(vp,
(uio->uio_rw == UIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh);
fufh_type = (uio->uio_rw == UIO_READ) ? FUFH_RDONLY : FUFH_WRONLY;
err = fuse_filehandle_getrw(vp, fufh_type, &fufh, cred, pid);
if (err) {
printf("FUSE: io dispatch: filehandles are closed\n");
return err;
@ -159,7 +160,7 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
} else {
SDT_PROBE2(fuse, , io, trace, 1,
"buffered read of vnode");
err = fuse_read_biobackend(vp, uio, cred, fufh);
err = fuse_read_biobackend(vp, uio, cred, fufh, pid);
}
break;
case UIO_WRITE:
@ -172,11 +173,13 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
if (directio || fuse_data_cache_mode == FUSE_CACHE_WT) {
SDT_PROBE2(fuse, , io, trace, 1,
"direct write of vnode");
err = fuse_write_directbackend(vp, uio, cred, fufh, ioflag);
err = fuse_write_directbackend(vp, uio, cred, fufh,
ioflag);
} else {
SDT_PROBE2(fuse, , io, trace, 1,
"buffered write of vnode");
err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag);
err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag,
pid);
}
break;
default:
@ -191,7 +194,7 @@ SDT_PROBE_DEFINE2(fuse, , io, read_bio_backend_feed, "int", "int");
SDT_PROBE_DEFINE3(fuse, , io, read_bio_backend_end, "int", "ssize_t", "int");
static int
fuse_read_biobackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh)
struct ucred *cred, struct fuse_filehandle *fufh, pid_t pid)
{
struct buf *bp;
daddr_t lbn;
@ -405,7 +408,7 @@ SDT_PROBE_DEFINE2(fuse, , io, write_biobackend_append_race, "long", "int");
static int
fuse_write_biobackend(struct vnode *vp, struct uio *uio,
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag)
struct ucred *cred, struct fuse_filehandle *fufh, int ioflag, pid_t pid)
{
struct fuse_vnode_data *fvdat = VTOFUD(vp);
struct buf *bp;
@ -625,7 +628,7 @@ again:
} while (uio->uio_resid > 0 && n > 0);
if (fuse_sync_resize && (fvdat->flag & FN_SIZECHANGE) != 0)
fuse_vnode_savesize(vp, cred);
fuse_vnode_savesize(vp, cred, pid);
return (err);
}
@ -640,14 +643,18 @@ fuse_io_strategy(struct vnode *vp, struct buf *bp)
struct uio uio;
struct iovec io;
int error = 0;
fufh_type_t fufh_type;
/* We don't know the true pid when we're dealing with the cache */
pid_t pid = 0;
const int biosize = fuse_iosize(vp);
MPASS(vp->v_type == VREG || vp->v_type == VDIR);
MPASS(bp->b_iocmd == BIO_READ || bp->b_iocmd == BIO_WRITE);
error = fuse_filehandle_getrw(vp,
(bp->b_iocmd == BIO_READ) ? FUFH_RDONLY : FUFH_WRONLY, &fufh);
fufh_type = bp->b_iocmd == BIO_READ ? FUFH_RDONLY : FUFH_WRONLY;
cred = bp->b_iocmd == BIO_READ ? bp->b_rcred : bp->b_wcred;
error = fuse_filehandle_getrw(vp, fufh_type, &fufh, cred, pid);
if (bp->b_iocmd == BIO_READ && error == EBADF) {
/*
* This may be a read-modify-write operation on a cached file
@ -655,7 +662,8 @@ fuse_io_strategy(struct vnode *vp, struct buf *bp)
*
* TODO: eliminate this hacky check once the FUFH table is gone
*/
error = fuse_filehandle_get(vp, FUFH_WRONLY, &fufh);
fufh_type = FUFH_WRONLY;
error = fuse_filehandle_get(vp, fufh_type, &fufh, cred, pid);
}
if (error) {
printf("FUSE: strategy: filehandles are closed\n");
@ -664,7 +672,6 @@ fuse_io_strategy(struct vnode *vp, struct buf *bp)
bufdone(bp);
return (error);
}
cred = bp->b_iocmd == BIO_READ ? bp->b_rcred : bp->b_wcred;
uiop = &uio;
uiop->uio_iov = &io;

View File

@ -61,7 +61,7 @@
#define _FUSE_IO_H_
int fuse_io_dispatch(struct vnode *vp, struct uio *uio, int ioflag,
struct ucred *cred);
struct ucred *cred, pid_t pid);
int fuse_io_strategy(struct vnode *vp, struct buf *bp);
int fuse_io_flushbuf(struct vnode *vp, int waitfor, struct thread *td);
int fuse_io_invalbuf(struct vnode *vp, struct thread *td);

View File

@ -345,7 +345,7 @@ fuse_vnode_open(struct vnode *vp, int32_t fuse_open_flags, struct thread *td)
}
int
fuse_vnode_savesize(struct vnode *vp, struct ucred *cred)
fuse_vnode_savesize(struct vnode *vp, struct ucred *cred, pid_t pid)
{
struct fuse_vnode_data *fvdat = VTOFUD(vp);
struct thread *td = curthread;
@ -377,7 +377,7 @@ fuse_vnode_savesize(struct vnode *vp, struct ucred *cred)
fsai->size = fvdat->filesize;
fsai->valid |= FATTR_SIZE;
fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh);
fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh, cred, pid);
if (fufh) {
fsai->fh = fufh->fh_id;
fsai->valid |= FATTR_FH;

View File

@ -126,7 +126,7 @@ void fuse_vnode_open(struct vnode *vp, int32_t fuse_open_flags,
int fuse_vnode_refreshsize(struct vnode *vp, struct ucred *cred);
int fuse_vnode_savesize(struct vnode *vp, struct ucred *cred);
int fuse_vnode_savesize(struct vnode *vp, struct ucred *cred, pid_t pid);
int fuse_vnode_setsize(struct vnode *vp, struct ucred *cred, off_t newsize);

View File

@ -216,6 +216,16 @@ uma_zone_t fuse_pbuf_zone;
#define fuse_vm_page_lock_queues() ((void)0)
#define fuse_vm_page_unlock_queues() ((void)0)
/* Get a filehandle for a directory */
static int
fuse_filehandle_get_dir(struct vnode *vp, struct fuse_filehandle **fufhp,
struct ucred *cred, pid_t pid)
{
if (fuse_filehandle_get(vp, FUFH_RDONLY, fufhp, cred, pid) == 0)
return 0;
return fuse_filehandle_get(vp, FUFH_EXEC, fufhp, cred, pid);
}
/*
struct vnop_access_args {
struct vnode *a_vp;
@ -278,6 +288,8 @@ fuse_vnop_close(struct vop_close_args *ap)
struct vnode *vp = ap->a_vp;
struct ucred *cred = ap->a_cred;
int fflag = ap->a_fflag;
struct thread *td = ap->a_td;
pid_t pid = td->td_proc->p_pid;
if (fuse_isdeadfs(vp)) {
return 0;
@ -285,8 +297,7 @@ fuse_vnop_close(struct vop_close_args *ap)
if (vnode_isdir(vp)) {
struct fuse_filehandle *fufh;
if ((fuse_filehandle_get(vp, O_RDONLY, &fufh) == 0) ||
(fuse_filehandle_get(vp, O_EXEC, &fufh) == 0))
if (fuse_filehandle_get_dir(vp, &fufh, cred, pid) == 0)
fuse_filehandle_close(vp, fufh, NULL, cred);
return 0;
}
@ -295,7 +306,7 @@ fuse_vnop_close(struct vop_close_args *ap)
}
/* TODO: close the file handle, if we're sure it's no longer used */
if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) {
fuse_vnode_savesize(vp, cred);
fuse_vnode_savesize(vp, cred, td->td_proc->p_pid);
}
return 0;
}
@ -432,7 +443,8 @@ fuse_vnop_create(struct vop_create_args *ap)
}
ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create");
fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, foo->fh);
fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td->td_proc->p_pid, cred,
foo->fh);
fuse_vnode_open(*vpp, foo->open_flags, td);
cache_purge_negative(dvp);
@ -597,7 +609,7 @@ fuse_vnop_inactive(struct vop_inactive_args *ap)
LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) {
if (need_flush && vp->v_type == VREG) {
if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) {
fuse_vnode_savesize(vp, NULL);
fuse_vnode_savesize(vp, NULL, 0);
}
if (fuse_data_cache_invalidate ||
(fvdat->flag & FN_REVOKED) != 0)
@ -1194,6 +1206,7 @@ fuse_vnop_open(struct vop_open_args *ap)
int mode = ap->a_mode;
struct thread *td = ap->a_td;
struct ucred *cred = ap->a_cred;
pid_t pid = td->td_proc->p_pid;
fufh_type_t fufh_type;
struct fuse_vnode_data *fvdat;
@ -1209,7 +1222,7 @@ fuse_vnop_open(struct vop_open_args *ap)
fufh_type = fuse_filehandle_xlate_from_fflags(mode);
if (fuse_filehandle_validrw(vp, fufh_type) != FUFH_INVALID) {
if (fuse_filehandle_validrw(vp, fufh_type, cred, pid)) {
fuse_vnode_open(vp, 0, td);
return 0;
}
@ -1257,6 +1270,7 @@ fuse_vnop_read(struct vop_read_args *ap)
struct uio *uio = ap->a_uio;
int ioflag = ap->a_ioflag;
struct ucred *cred = ap->a_cred;
pid_t pid = curthread->td_proc->p_pid;
if (fuse_isdeadfs(vp)) {
return ENXIO;
@ -1266,7 +1280,7 @@ fuse_vnop_read(struct vop_read_args *ap)
ioflag |= IO_DIRECT;
}
return fuse_io_dispatch(vp, uio, ioflag, cred);
return fuse_io_dispatch(vp, uio, ioflag, cred, pid);
}
/*
@ -1285,12 +1299,11 @@ fuse_vnop_readdir(struct vop_readdir_args *ap)
struct vnode *vp = ap->a_vp;
struct uio *uio = ap->a_uio;
struct ucred *cred = ap->a_cred;
struct fuse_filehandle *fufh = NULL;
struct fuse_iov cookediov;
int err = 0;
int freefufh = 0;
pid_t pid = curthread->td_proc->p_pid;
if (fuse_isdeadfs(vp)) {
return ENXIO;
@ -1300,7 +1313,7 @@ fuse_vnop_readdir(struct vop_readdir_args *ap)
return EINVAL;
}
if ((err = fuse_filehandle_get(vp, FUFH_RDONLY, &fufh)) != 0) {
if ((err = fuse_filehandle_get_dir(vp, &fufh, cred, pid)) != 0) {
SDT_PROBE2(fuse, , vnops, trace, 1,
"calling readdir() before open()");
err = fuse_filehandle_open(vp, O_RDONLY, &fufh, NULL, cred);
@ -1550,6 +1563,7 @@ fuse_vnop_setattr(struct vop_setattr_args *ap)
struct fuse_dispatcher fdi;
struct fuse_setattr_in *fsai;
struct fuse_access_param facp;
pid_t pid = td->td_proc->p_pid;
int err = 0;
enum vtype vtyp;
@ -1589,7 +1603,7 @@ fuse_vnop_setattr(struct vop_setattr_args *ap)
newsize = vap->va_size;
fsai->valid |= FATTR_SIZE;
fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh);
fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh, cred, pid);
if (fufh) {
fsai->fh = fufh->fh_id;
fsai->valid |= FATTR_FH;
@ -1760,6 +1774,7 @@ fuse_vnop_write(struct vop_write_args *ap)
struct uio *uio = ap->a_uio;
int ioflag = ap->a_ioflag;
struct ucred *cred = ap->a_cred;
pid_t pid = curthread->td_proc->p_pid;
int err;
if (fuse_isdeadfs(vp)) {
@ -1773,7 +1788,7 @@ fuse_vnop_write(struct vop_write_args *ap)
ioflag |= IO_DIRECT;
}
return fuse_io_dispatch(vp, uio, ioflag, cred);
return fuse_io_dispatch(vp, uio, ioflag, cred, pid);
}
SDT_PROBE_DEFINE1(fuse, , vnops, vnop_getpages_error, "int");
@ -1797,6 +1812,7 @@ fuse_vnop_getpages(struct vop_getpages_args *ap)
struct thread *td;
struct ucred *cred;
vm_page_t *pages;
pid_t pid = curthread->td_proc->p_pid;
vp = ap->a_vp;
KASSERT(vp->v_object, ("objectless vp passed to getpages"));
@ -1846,7 +1862,7 @@ fuse_vnop_getpages(struct vop_getpages_args *ap)
uio.uio_rw = UIO_READ;
uio.uio_td = td;
error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred);
error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred, pid);
pmap_qremove(kva, npages);
uma_zfree(fuse_pbuf_zone, bp);
@ -1929,6 +1945,7 @@ fuse_vnop_putpages(struct vop_putpages_args *ap)
struct ucred *cred;
vm_page_t *pages;
vm_ooffset_t fsize;
pid_t pid = curthread->td_proc->p_pid;
vp = ap->a_vp;
KASSERT(vp->v_object, ("objectless vp passed to putpages"));
@ -1978,7 +1995,7 @@ fuse_vnop_putpages(struct vop_putpages_args *ap)
uio.uio_rw = UIO_WRITE;
uio.uio_td = td;
error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred);
error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred, pid);
pmap_qremove(kva, npages);
uma_zfree(fuse_pbuf_zone, bp);

View File

@ -99,8 +99,7 @@ TEST_F(AllowOther, allowed)
* visible to root. The second process is unprivileged and shouldn't be able
* to open the file, but does thanks to the bug
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236844 */
TEST_F(AllowOther, DISABLED_privilege_escalation)
TEST_F(AllowOther, privilege_escalation)
{
const static char FULLPATH[] = "mountpoint/some_file.txt";
const static char RELPATH[] = "some_file.txt";

View File

@ -165,8 +165,7 @@ TEST_F(Open, fifo)
* credentials open the same file, even if they use the same mode. This is
* necessary so that the daemon can validate each set of credentials.
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236844 */
TEST_F(Open, DISABLED_multiple_creds)
TEST_F(Open, multiple_creds)
{
const static char FULLPATH[] = "mountpoint/some_file.txt";
const static char RELPATH[] = "some_file.txt";