git: f9c9122d5ab9 - main - fusefs: First take on exterrorizing
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 17 Jun 2025 06:11:41 UTC
The branch main has been updated by arrowd:
URL: https://cgit.FreeBSD.org/src/commit/?id=f9c9122d5ab9b106ddc6897454350b31de838631
commit f9c9122d5ab9b106ddc6897454350b31de838631
Author: Gleb Popov <arrowd@FreeBSD.org>
AuthorDate: 2025-06-13 10:38:35 +0000
Commit: Gleb Popov <arrowd@FreeBSD.org>
CommitDate: 2025-06-17 06:11:34 +0000
fusefs: First take on exterrorizing
Reviewed by: kib, asomers
Approved by: kib, asomers
Differential Revision: https://reviews.freebsd.org/D50831
---
sys/fs/fuse/fuse_device.c | 34 +++++++++++++++++++++-------------
sys/fs/fuse/fuse_vfsops.c | 33 +++++++++++++++++++++------------
sys/sys/exterr_cat.h | 1 +
3 files changed, 43 insertions(+), 25 deletions(-)
diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
index 0a5da63c1f54..b0c886d4b120 100644
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -82,6 +82,8 @@
#include <sys/sysctl.h>
#include <sys/poll.h>
#include <sys/selinfo.h>
+#define EXTERR_CATEGORY EXTERR_CAT_FUSE
+#include <sys/exterrvar.h>
#include "fuse.h"
#include "fuse_internal.h"
@@ -193,7 +195,7 @@ fuse_device_filter(struct cdev *dev, struct knote *kn)
kn->kn_fop = &fuse_device_wfiltops;
error = 0;
} else if (error == 0) {
- error = EINVAL;
+ error = EXTERROR(EINVAL, "Unsupported kevent filter");
kn->kn_data = error;
}
@@ -319,7 +321,7 @@ again:
"we know early on that reader should be kicked so we "
"don't wait for news");
fuse_lck_mtx_unlock(data->ms_mtx);
- return (ENODEV);
+ return (EXTERROR(ENODEV, "This FUSE session is about to be closed"));
}
if (!(tick = fuse_ms_pop(data))) {
/* check if we may block */
@@ -331,7 +333,10 @@ again:
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))
+ err = EXTERROR(ENODEV,
+ "This FUSE session is about to be closed");
+ return (err);
}
tick = fuse_ms_pop(data);
}
@@ -361,8 +366,8 @@ again:
FUSE_ASSERT_MS_DONE(tick);
fuse_ticket_drop(tick);
}
- return (ENODEV); /* This should make the daemon get off
- * of us */
+ /* This should make the daemon get off of us */
+ return (EXTERROR(ENODEV, "This FUSE session is about to be closed"));
}
SDT_PROBE2(fusefs, , device, trace, 1,
"fuse device read message successfully");
@@ -385,7 +390,7 @@ again:
fdata_set_dead(data);
SDT_PROBE2(fusefs, , device, trace, 2,
"daemon is stupid, kick it off...");
- err = ENODEV;
+ err = EXTERROR(ENODEV, "Partial read attempted");
} else {
err = uiomove(buf, buflen, uio);
}
@@ -403,12 +408,14 @@ fuse_ohead_audit(struct fuse_out_header *ohead, struct uio *uio)
SDT_PROBE2(fusefs, , device, trace, 1,
"Format error: body size "
"differs from size claimed by header");
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Format error: body size "
+ "differs from size claimed by header"));
}
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");
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Format error: non zero error, "
+ "but message had a body"));
}
return (0);
@@ -444,7 +451,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
SDT_PROBE2(fusefs, , device, trace, 1,
"fuse_device_write got less than a header!");
fdata_set_dead(data);
- return (EINVAL);
+ return (EXTERROR(EINVAL, "fuse_device_write got less than a header!"));
}
if ((err = uiomove(&ohead, sizeof(struct fuse_out_header), uio)) != 0)
return (err);
@@ -452,7 +459,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
if (data->linux_errnos != 0 && ohead.error != 0) {
err = -ohead.error;
if (err < 0 || err >= nitems(linux_to_bsd_errtbl))
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Unknown Linux errno", err));
/* '-', because it will get flipped again below */
ohead.error = -linux_to_bsd_errtbl[err];
@@ -520,7 +527,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
memcpy(&tick->tk_aw_ohead, &ohead,
sizeof(ohead));
tick->tk_aw_handler(tick, uio);
- err = EINVAL;
+ err = EXTERROR(EINVAL, "Unknown errno", ohead.error);
} else {
memcpy(&tick->tk_aw_ohead, &ohead,
sizeof(ohead));
@@ -570,7 +577,8 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
/* Unimplemented. See comments in fuse_vnops */
default:
/* Not implemented */
- err = ENOSYS;
+ err = EXTERROR(ENOSYS, "Unimplemented FUSE notification code",
+ ohead.error);
}
vfs_unbusy(mp);
} else {
@@ -589,7 +597,7 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag)
*/
err = 0;
} else {
- err = EINVAL;
+ err = EXTERROR(ENOSYS, "FUSE ticket is missing");
}
}
diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c
index 48b84d3c75af..1b858a988289 100644
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -81,6 +81,8 @@
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <sys/fcntl.h>
+#define EXTERR_CATEGORY EXTERR_CAT_FUSE
+#include <sys/exterrvar.h>
#include "fuse.h"
#include "fuse_node.h"
@@ -272,7 +274,7 @@ fuse_vfsop_fhtovp(struct mount *mp, struct fid *fhp, int flags,
int error;
if (!(fuse_get_mpdata(mp)->dataflags & FSESS_EXPORT_SUPPORT))
- return EOPNOTSUPP;
+ return (EXTERROR(EOPNOTSUPP, "NFS-style lookups are not supported"));
error = VFS_VGET(mp, ffhp->nid, LK_EXCLUSIVE, &nvp);
if (error) {
@@ -321,11 +323,11 @@ fuse_vfsop_mount(struct mount *mp)
opts = mp->mnt_optnew;
if (!opts)
- return EINVAL;
+ return (EXTERROR(EINVAL, "Mount options were not supplied"));
/* `fspath' contains the mount point (eg. /mnt/fuse/sshfs); REQUIRED */
if (!vfs_getopts(opts, "fspath", &err))
- return err;
+ return (EXTERROR(err, "Mount options are missing 'fspath'"));
/*
* With the help of underscored options the mount program
@@ -358,11 +360,12 @@ fuse_vfsop_mount(struct mount *mp)
/* `from' contains the device name (eg. /dev/fuse0); REQUIRED */
fspec = vfs_getopts(opts, "from", &err);
if (!fspec)
- return err;
+ return (EXTERROR(err, "Mount options are missing 'from'"));
/* `fd' contains the filedescriptor for this session; REQUIRED */
if (vfs_scanopt(opts, "fd", "%d", &fd) != 1)
- return EINVAL;
+ return (EXTERROR(EINVAL, "Mount options contain an invalid value "
+ "for 'fd'"));
err = fuse_getdevice(fspec, td, &fdev);
if (err != 0)
@@ -398,11 +401,17 @@ fuse_vfsop_mount(struct mount *mp)
/* 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)
+ EXTERROR(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);
+ EXTERROR(err, "Mounting as a user that is different from the FUSE "
+ "daemon's requires privileges");
+ }
if (err) {
FUSE_UNLOCK();
goto out;
@@ -549,7 +558,7 @@ fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
* nullfs mount of a fusefs file system.
*/
SDT_PROBE1(fusefs, , vfsops, invalidate_without_export, mp);
- return (EOPNOTSUPP);
+ return (EXTERROR(EOPNOTSUPP, "NFS-style lookups are not supported"));
}
error = fuse_internal_get_cached_vnode(mp, ino, flags, vpp);
@@ -580,10 +589,10 @@ fuse_vfsop_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
* Something is very wrong with the server if "foo/." has a
* different inode number than "foo".
*/
- fuse_warn(data, FSESS_WARN_DOT_LOOKUP,
- "Inconsistent LOOKUP response: \"FILE/.\" has a different "
- "inode number than \"FILE\".");
- error = EIO;
+ static const char exterr[] = "Inconsistent LOOKUP response: "
+ "\"FILE/.\" has a different inode number than \"FILE\".";
+ fuse_warn(data, FSESS_WARN_DOT_LOOKUP, exterr);
+ error = EXTERROR(EIO, exterr);
goto out;
}
diff --git a/sys/sys/exterr_cat.h b/sys/sys/exterr_cat.h
index adb474e84c1b..d770c274d7b7 100644
--- 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