diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c --- a/sys/fs/fuse/fuse_device.c +++ b/sys/fs/fuse/fuse_device.c @@ -82,6 +82,8 @@ #include #include #include +#define EXTERR_CATEGORY EXTERR_CAT_FUSE +#include #include "fuse.h" #include "fuse_internal.h" @@ -193,6 +195,7 @@ kn->kn_fop = &fuse_device_wfiltops; error = 0; } else if (error == 0) { + SET_ERROR0(EINVAL, "Invalid kevent filter"); error = EINVAL; kn->kn_data = error; } @@ -319,6 +322,7 @@ "we know early on that reader should be kicked so we " "don't wait for news"); fuse_lck_mtx_unlock(data->ms_mtx); + SET_ERROR0(ENODEV, "This FUSE session is about to be closed"); return (ENODEV); } if (!(tick = fuse_ms_pop(data))) { @@ -331,7 +335,11 @@ err = msleep(data, &data->ms_mtx, PCATCH, "fu_msg", 0); if (err != 0) { fuse_lck_mtx_unlock(data->ms_mtx); - return (fdata_get_dead(data) ? ENODEV : err); + if (fdata_get_dead(data)) { + SET_ERROR0(ENODEV, "This FUSE session is about to be closed"); + return (ENODEV); + } + return (err); } tick = fuse_ms_pop(data); } @@ -361,6 +369,7 @@ FUSE_ASSERT_MS_DONE(tick); fuse_ticket_drop(tick); } + SET_ERROR0(ENODEV, "This FUSE session is about to be closed"); return (ENODEV); /* This should make the daemon get off * of us */ } @@ -385,6 +394,7 @@ fdata_set_dead(data); SDT_PROBE2(fusefs, , device, trace, 2, "daemon is stupid, kick it off..."); + SET_ERROR0(ENODEV, "Partial read attempted"); err = ENODEV; } else { err = uiomove(buf, buflen, uio); @@ -400,14 +410,17 @@ fuse_ohead_audit(struct fuse_out_header *ohead, struct uio *uio) { if (uio->uio_resid + sizeof(struct fuse_out_header) != ohead->len) { - SDT_PROBE2(fusefs, , device, trace, 1, - "Format error: body size " - "differs from size claimed by header"); + static const char* exterr = "Format error: body size " + "differs from size claimed by header"; + SDT_PROBE2(fusefs, , device, trace, 1, exterr); + SET_ERROR0(EINVAL, exterr); return (EINVAL); } if (uio->uio_resid && ohead->unique != 0 && ohead->error) { - SDT_PROBE2(fusefs, , device, trace, 1, - "Format error: non zero error but message had a body"); + static const char* exterr = "Format error: non zero " + "error, but message has a body"; + SDT_PROBE2(fusefs, , device, trace, 1, exterr); + SET_ERROR0(EINVAL, exterr); return (EINVAL); } @@ -441,9 +454,10 @@ return (err); if (uio->uio_resid < sizeof(struct fuse_out_header)) { - SDT_PROBE2(fusefs, , device, trace, 1, - "fuse_device_write got less than a header!"); + static const char* exterr = "fuse_device_write got less than a header!"; + SDT_PROBE2(fusefs, , device, trace, 1, exterr); fdata_set_dead(data); + SET_ERROR0(EINVAL, exterr); return (EINVAL); } if ((err = uiomove(&ohead, sizeof(struct fuse_out_header), uio)) != 0) @@ -451,8 +465,10 @@ if (data->linux_errnos != 0 && ohead.error != 0) { err = -ohead.error; - if (err < 0 || err >= nitems(linux_to_bsd_errtbl)) + if (err < 0 || err >= nitems(linux_to_bsd_errtbl)) { + SET_ERROR0(EINVAL, "Unknown Linux errno"); return (EINVAL); + } /* '-', because it will get flipped again below */ ohead.error = -linux_to_bsd_errtbl[err]; @@ -520,6 +536,7 @@ memcpy(&tick->tk_aw_ohead, &ohead, sizeof(ohead)); tick->tk_aw_handler(tick, uio); + SET_ERROR0(EINVAL, "Unknown Linux errno"); err = EINVAL; } else { memcpy(&tick->tk_aw_ohead, &ohead, @@ -570,6 +587,7 @@ /* Unimplemented. See comments in fuse_vnops */ default: /* Not implemented */ + SET_ERROR0(ENOSYS, "Unknown FUSE error in out header"); err = ENOSYS; } vfs_unbusy(mp); @@ -589,6 +607,7 @@ */ err = 0; } else { + SET_ERROR0(ENOSYS, "FUSE ticket is missing"); err = EINVAL; } } diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c --- a/sys/fs/fuse/fuse_vfsops.c +++ b/sys/fs/fuse/fuse_vfsops.c @@ -81,6 +81,8 @@ #include #include #include +#define EXTERR_CATEGORY EXTERR_CAT_FUSE +#include #include "fuse.h" #include "fuse_node.h" @@ -271,8 +273,10 @@ struct vnode *nvp; int error; - if (!(fuse_get_mpdata(mp)->dataflags & FSESS_EXPORT_SUPPORT)) + if (!(fuse_get_mpdata(mp)->dataflags & FSESS_EXPORT_SUPPORT)) { + SET_ERROR0(EOPNOTSUPP, "NFS-style lookups are not supported"); return EOPNOTSUPP; + } error = VFS_VGET(mp, ffhp->nid, LK_EXCLUSIVE, &nvp); if (error) { @@ -320,12 +324,16 @@ /* Get the new options passed to mount */ opts = mp->mnt_optnew; - if (!opts) + if (!opts) { + SET_ERROR0(EINVAL, "Mount options were not supplied"); return EINVAL; + } /* `fspath' contains the mount point (eg. /mnt/fuse/sshfs); REQUIRED */ - if (!vfs_getopts(opts, "fspath", &err)) + if (!vfs_getopts(opts, "fspath", &err)) { + SET_ERROR0(err, "Mount options are missing 'fspath'"); return err; + } /* * With the help of underscored options the mount program @@ -357,12 +365,16 @@ /* `from' contains the device name (eg. /dev/fuse0); REQUIRED */ fspec = vfs_getopts(opts, "from", &err); - if (!fspec) + if (!fspec) { + SET_ERROR0(err, "Mount options are missing 'from'"); return err; + } /* `fd' contains the filedescriptor for this session; REQUIRED */ - if (vfs_scanopt(opts, "fd", "%d", &fd) != 1) + if (vfs_scanopt(opts, "fd", "%d", &fd) != 1) { + SET_ERROR0(EINVAL, "Mount options are missing 'fd'"); return EINVAL; + } err = fuse_getdevice(fspec, td, &fdev); if (err != 0) @@ -398,11 +410,15 @@ /* Sanity + permission checks */ if (!data->daemoncred) panic("fuse daemon found, but identity unknown"); - if (mntopts & FSESS_DAEMON_CAN_SPY) + if (mntopts & FSESS_DAEMON_CAN_SPY) { err = priv_check(td, PRIV_VFS_FUSE_ALLOWOTHER); - if (err == 0 && td->td_ucred->cr_uid != data->daemoncred->cr_uid) + SET_ERROR0(err, "FUSE daemon requires privileges due to 'allow_other' option"); + } + if (err == 0 && td->td_ucred->cr_uid != data->daemoncred->cr_uid) { /* are we allowed to do the first mount? */ err = priv_check(td, PRIV_VFS_FUSE_MOUNT_NONUSER); + SET_ERROR0(err, "Mounting as an user that is different from FUSE daemon's one requires privileges"); + } if (err) { FUSE_UNLOCK(); goto out; @@ -549,6 +565,7 @@ * nullfs mount of a fusefs file system. */ SDT_PROBE1(fusefs, , vfsops, invalidate_without_export, mp); + SET_ERROR0(EOPNOTSUPP, "NFS-style lookups are not supported"); return (EOPNOTSUPP); } diff --git a/sys/sys/exterr_cat.h b/sys/sys/exterr_cat.h --- a/sys/sys/exterr_cat.h +++ b/sys/sys/exterr_cat.h @@ -15,6 +15,7 @@ #define EXTERR_CAT_FILEDESC 2 #define EXTERR_KTRACE 3 /* To allow inclusion of this file into kern_ktrace.c */ +#define EXTERR_CAT_FUSE 4 #endif