diff options
author | Alik Aslanyan <inline0@pm.me> | 2025-09-09 23:35:40 +0400 |
---|---|---|
committer | Bernd Schubert <bernd@bsbernd.com> | 2025-09-19 00:14:45 +0200 |
commit | 52a633a5d4435f1965fc8d44cf9a705e6679f793 (patch) | |
tree | e524a3d64550dd45f6d276076ad6b898b53503a1 | |
parent | 6e4557c57c4ce63de4042f77dcbf58627d13a59b (diff) | |
download | libfuse-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>
-rw-r--r-- | include/fuse_lowlevel.h | 2 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 26 |
2 files changed, 27 insertions, 1 deletions
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index a6cce01..312b331 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -2115,6 +2115,8 @@ fuse_session_new_versioned(struct fuse_args *args, * If not all options are known, an error message is written to stderr * and the function returns NULL. * + * To create a no-op session just for mounting pass op as NULL. + * * Option parsing skips argv[0], which is assumed to contain the * program name. To prevent accidentally passing an option in * argv[0], this element must always be present (even if no options 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); } |