[PATCH] Fix memory leak in high level API (#781)
authorMatthias Görgens <matthias.goergens@gmail.com>
Fri, 14 Apr 2023 11:19:03 +0000 (19:19 +0800)
committerLaszlo Boszormenyi (GCS) <gcs@debian.org>
Tue, 18 Apr 2023 21:07:15 +0000 (23:07 +0200)
Previously, in the high level API if we received a signal between
setting up signal handlers and processing INIT, we would leak

```
$ ./example/hello -s -d -f mountpoint/
[9/9] Linking target example/hello_ll
FUSE library version: 3.14.1
nullpath_ok: 0

=================================================================
==178330==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 352 byte(s) in 1 object(s) allocated from:
    #0 0x7fbb19abf411 in __interceptor_calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7fbb1a0efd3b in fuse_fs_new ../lib/fuse.c:4814
    #2 0x7fbb1a0f02b5 in fuse_new_31 ../lib/fuse.c:4913
    #3 0x7fbb1a10ec5e in fuse_main_real ../lib/helper.c:345
    #4 0x5625db8ab418 in main ../example/hello.c:176
    #5 0x7fbb1983c78f  (/usr/lib/libc.so.6+0x2378f)

SUMMARY: AddressSanitizer: 352 byte(s) leaked in 1 allocation(s).
```

That's because `fuse_lowlevel.c`s `fuse_session_destroy` would only call
the user supplied `op.destroy`, if INIT had been processed, but the high
level API relied on `op.destroy` to free `f->fs`.

This patch moves the freeing into `fuse_destroy` that will always be
called by our high-level API.

Gbp-Pq: Name Fix_memory_leak_in_high_level_API.patch

lib/fuse.c

index a247d3c1cd2738ffa71d6cf1130b9ef44f3ea077..b8e2f0b76feef26b36d7b899ada30675b1816c2a 100644 (file)
@@ -2623,7 +2623,6 @@ void fuse_fs_destroy(struct fuse_fs *fs)
        fuse_get_context()->private_data = fs->user_data;
        if (fs->op.destroy)
                fs->op.destroy(fs->user_data);
-       free(fs);
 }
 
 static void fuse_lib_destroy(void *data)
@@ -2632,7 +2631,6 @@ static void fuse_lib_destroy(void *data)
 
        fuse_create_context(f);
        fuse_fs_destroy(f->fs);
-       f->fs = NULL;
 }
 
 static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent,
@@ -5084,6 +5082,7 @@ void fuse_destroy(struct fuse *f)
        free(f->name_table.array);
        pthread_mutex_destroy(&f->lock);
        fuse_session_destroy(f->se);
+       free(f->fs);
        free(f->conf.modules);
        free(f);
        fuse_delete_context_key();