aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAlik Aslanyan <inline0@pm.me>2025-09-09 23:35:40 +0400
committerBernd Schubert <bernd@bsbernd.com>2025-09-19 00:14:45 +0200
commit52a633a5d4435f1965fc8d44cf9a705e6679f793 (patch)
treee524a3d64550dd45f6d276076ad6b898b53503a1 /lib
parent6e4557c57c4ce63de4042f77dcbf58627d13a59b (diff)
downloadlibfuse-52a633a5d4435f1965fc8d44cf9a705e6679f793.tar.gz
fuse_lowlevel.c: allow passing ops as NULL
During testing of LACT using various sanitizers issue with libfuse.so leaking memory and reading uninitialized memory was uncovered. While this was due to ABI misusage on the side of fuser (Rust wrapper for libfuse.so), we now allow creating a no-op session by passing ops as NULL. fuser and other libfuse users is using fuse_session_new() with NULL struct fuse_lowlevel_ops *op and op_size=0. This resulted in a warning, but otherwise succeeded. The resulting fuse_session is just passed to fuse_session_mount() so that libfuse could do the actual mount. Fuse kernel request handling is not done through libfuse but their own layer. Edit by Bernd: - Update the commit message - moved using null_ops to fuse_session_new_30() as that is actually called by the external fuse_session_new(). - forbidding NULL struct fuse_lowlevel_ops *op and 0 op_size in fuse_session_new_versioned() - various other NULL ptr checks in fuse_session_new() that now result in failure. Signed-off-by: Alik Aslanyan <inline0@pm.me> Signed-off-by: Bernd Schubert <bernd@bsbernd.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/fuse_lowlevel.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 1e45315..cb757cd 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -4108,12 +4108,23 @@ fuse_session_new_versioned(struct fuse_args *args,
struct fuse_session *se;
struct mount_opts *mo;
+ if (op == NULL || op_size == 0) {
+ fuse_log(FUSE_LOG_ERR,
+ "fuse: warning: empty op list passed to fuse_session_new()\n");
+ return NULL;
+ }
+
+ if (version == NULL) {
+ fuse_log(FUSE_LOG_ERR, "fuse: warning: version not passed to fuse_session_new()\n");
+ return NULL;
+ }
+
if (sizeof(struct fuse_lowlevel_ops) < op_size) {
fuse_log(FUSE_LOG_ERR, "fuse: warning: library too old, some operations may not work\n");
op_size = sizeof(struct fuse_lowlevel_ops);
}
- if (args->argc == 0) {
+ if (args == NULL || args->argc == 0) {
fuse_log(FUSE_LOG_ERR, "fuse: empty argv passed to fuse_session_new().\n");
return NULL;
}
@@ -4225,9 +4236,22 @@ struct fuse_session *fuse_session_new_30(struct fuse_args *args,
size_t op_size,
void *userdata)
{
+ struct fuse_lowlevel_ops null_ops = { 0 };
+
/* unknown version */
struct libfuse_version version = { 0 };
+ /*
+ * This function is the ABI interface function from fuse_session_new in
+ * compat.c. External libraries like "fuser" might call fuse_session_new()
+ * with NULL ops and then pass that session to fuse_session_mount().
+ * The actual FUSE operations are handled in their own library.
+ */
+ if (op == NULL) {
+ op = &null_ops;
+ op_size = sizeof(null_ops);
+ }
+
return fuse_session_new_versioned(args, op, op_size, &version,
userdata);
}