[PATCH 7.0 16/42] fuse: abort on fatal signal during sync init

Greg Kroah-Hartman
2026-04-24T13:32:16Z

From: Miklos Szeredi <mszeredi@redhat.com>

commit 204aa22a686bfee48daca7db620c1e017615f2ff upstream.

When sync init is used and the server exits for some reason (error, crash)
while processing FUSE_INIT, the filesystem creation will hang. The reason
is that while all other threads will exit, the mounting thread (or process)
will keep the device fd open, which will prevent an abort from happening.

This is a regression from the async mount case, where the mount was done
first, and the FUSE_INIT processing afterwards, in which case there's no
such recursive syscall keeping the fd open.

Fixes: dfb84c330794 ("fuse: allow synchronous FUSE_INIT")
Cc: stable@vger.kernel.org # v6.18
Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Bernd Schubert <bernd@bsbernd.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/fuse/dev.c | 8 +++++++-
fs/fuse/fuse_i.h | 1 +
fs/fuse/inode.c | 1 +
3 files changed, 9 insertions(+), 1 deletion(-)

--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -570,6 +570,11 @@ static void request_wait_answer(struct f
if (!err)
return;

+ if (req->args->abort_on_kill) {
+ fuse_abort_conn(fc);
+ return;
+ }
+
if (test_bit(FR_URING, &req->flags))
removed = fuse_uring_remove_pending_req(req);
else
@@ -676,7 +681,8 @@ ssize_t __fuse_simple_request(struct mnt
fuse_force_creds(req);

__set_bit(FR_WAITING, &req->flags);
- __set_bit(FR_FORCE, &req->flags);
+ if (!args->abort_on_kill)
+ __set_bit(FR_FORCE, &req->flags);
} else {
WARN_ON(args->nocreds);
req = fuse_get_req(idmap, fm, false);
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -345,6 +345,7 @@ struct fuse_args {
bool is_ext:1;
bool is_pinned:1;
bool invalidate_vmap:1;
+ bool abort_on_kill:1;
struct fuse_in_arg in_args[4];
struct fuse_arg out_args[2];
void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1551,6 +1551,7 @@ int fuse_send_init(struct fuse_mount *fm
int err;

if (fm->fc->sync_init) {
+ ia->args.abort_on_kill = true;
err = fuse_simple_request(fm, &ia->args);
/* Ignore size of init reply */
if (err > 0)