Discussion:
[fuse-devel] [Patch] fuse: fix possible infinite recursion in fuse_new_30()
Chris Clayton via fuse-devel
2017-07-13 13:01:40 UTC
Permalink
Under certain circumstances, lib/fuse.c:fuse_new_30() calls lib/fuse.c:fuse_new(). Once built,
libfuse.so.3.1.0 contains three (versioned) symbols with the name fuse_new:

- ***@FUSE_3.0, an alias of fuse_new_30();
- another ***@FUSE_3.0, the real fuse_new(); and
- ***@FUSE_3.1, another reference to the real fuse_new().

(These versioned symbols are intended to provide backward compatibility for applications written for/built.
against libfuse3.so.3.0.x).
Unfortunately, the loader uses the first instance of ***@FUSE_3.0 listed above to resolve the call to fuse_new()
from fuse_new_30(). Obviously, this causes infinite recursion and, in the case of sshfs-3.0.0, a segmentation fault.

Fix this by renaming fuse_new() to fuse_new_31() and calling it explicitly from fuse_new_30(). Also create a
versioned symbol ***@FUSE_3.1 as an alias of fuse_new_31(). This gives us a library containing only two
symbols with the name fuse_new:

- ***@FUSE_3.0, an alias of fuse_new_30(); and
- ***@FUSE_3.1, an alias of fuse_new_31().

***@FUSE_3.1 is specified to be the default symbol used to resolve unversioned references to fuse_new();

Signed-off-by: Chris Clayton <***@googlemail.com>

---
diff -rup fuse-3.1.0.orig/lib/fuse.c fuse-3.1.0/lib/fuse.c
--- fuse-3.1.0.orig/lib/fuse.c 2017-07-08 11:48:08.000000000 +0100
+++ fuse-3.1.0/lib/fuse.c 2017-07-13 06:21:30.295879232 +0100
@@ -196,6 +196,12 @@ struct fuse_context_i {
fuse_req_t req;
};

+
+/* private function that (via symbol versioning below) is the default fuse_new()
+ * implementation for programs that define FUSE_USE_VERSION not equal to 30 */
+struct fuse *fuse_new_31(struct fuse_args *args, const struct fuse_operations *op,
+ size_t op_size, void *private_data);
+
/* Defined by FUSE_REGISTER_MODULE() in lib/modules/subdir.c and iconv.c. */
extern fuse_module_factory_t fuse_module_subdir_factory;
extern fuse_module_factory_t fuse_module_iconv_factory;
@@ -4629,7 +4635,7 @@ void fuse_stop_cleanup_thread(struct fus
/* Emulates 3.0-style fuse_new(), which processes
--help */
FUSE_SYMVER(".symver fuse_new_30,***@FUSE_3.0");
-FUSE_SYMVER(".symver fuse_new,fuse_new@@FUSE_3.1");
+FUSE_SYMVER(".symver fuse_new_31,fuse_new@@FUSE_3.1");
struct fuse *fuse_new_30(struct fuse_args *args,
const struct fuse_operations *op,
size_t op_size, void *user_data)
@@ -4649,10 +4655,10 @@ struct fuse *fuse_new_30(struct fuse_arg
fuse_lib_help(args);
return NULL;
} else
- return fuse_new(args, op, op_size, user_data);
+ return fuse_new_31(args, op, op_size, user_data);
}

-struct fuse *fuse_new(struct fuse_args *args,
+struct fuse *fuse_new_31(struct fuse_args *args,
const struct fuse_operations *op,
size_t op_size, void *user_data)
{
Nikolaus Rath
2017-07-13 14:08:19 UTC
Permalink
Post by Chris Clayton via fuse-devel
Under certain circumstances, lib/fuse.c:fuse_new_30() calls lib/fuse.c:fuse_new(). Once built,
[...]

Thanks, applied!

(The actual patch against master is a little smaller, since yours seems
to have been based on the most recent release).

Best,
-Nikolaus
--
GPG Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F

»Time flies like an arrow, fruit flies like a Banana.«
Loading...