diff options
author | Bernd Schubert <bschubert@ddn.com> | 2024-03-20 00:07:44 +0100 |
---|---|---|
committer | Bernd Schubert <bschubert@ddn.com> | 2024-03-20 12:32:39 +0100 |
commit | 982743f0cad20de044d9767c7c8c46887fcb80c3 (patch) | |
tree | f29ec29ca940508fcd8a182135ffb68118795e2e /example | |
parent | f041818c633645754ddc1ceabb002805739be7aa (diff) | |
download | libfuse-982743f0cad20de044d9767c7c8c46887fcb80c3.tar.gz |
Fix use-after-free in example/poll.c
As noticed by valgrind in issue #907 example/poll.c
triggers a use-after-free
==85200== Thread 2:
==85200== Invalid read of size 4
==85200== at 0x485E54A: send_notify_iov (fuse_lowlevel.c:2267)
==85200== by 0x485E54A: fuse_lowlevel_notify_poll (fuse_lowlevel.c:2289)
==85200== by 0x1096F2: fsel_producer (poll.c:245)
==85200== by 0x4897EA6: start_thread (pthread_create.c:477)
==85200== by 0x49ADA6E: clone (clone.S:95)
==85200== Address 0x5291d68 is 392 bytes inside a block of size 920 free'd
==85200== at 0x48399AB: free (vg_replace_malloc.c:538)
==85200== by 0x485A12C: fuse_destroy (fuse.c:5103)
==85200== by 0x486220F: fuse_main_real (helper.c:389)
==85200== by 0x1091D6: main (poll.c:288)
==85200== Block was alloc'd at
==85200== at 0x483AB65: calloc (vg_replace_malloc.c:760)
==85200== by 0x485BAA0: fuse_session_new (fuse_lowlevel.c:3036)
==85200== by 0x4859AF2: fuse_new@@FUSE_3.1 (fuse.c:4966)
==85200== by 0x4862129: fuse_main_real (helper.c:345)
==85200== by 0x1091D6: main (poll.c:288)
Issue is that the "fsel_producer" thread is still active after
fuse_destroy - it gets destructed too late.
Diffstat (limited to 'example')
-rw-r--r-- | example/poll.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/example/poll.c b/example/poll.c index f9430a9..fd53ec0 100644 --- a/example/poll.c +++ b/example/poll.c @@ -33,6 +33,7 @@ #include <time.h> #include <pthread.h> #include <poll.h> +#include <stdbool.h> /* * fsel_open_mask is used to limit the number of opens to 1 per file. @@ -51,6 +52,9 @@ static pthread_mutex_t fsel_mutex; /* protects notify_mask and cnt array */ static unsigned fsel_poll_notify_mask; /* poll notification scheduled? */ static struct fuse_pollhandle *fsel_poll_handle[FSEL_FILES]; /* poll notify handles */ static unsigned fsel_cnt[FSEL_FILES]; /* nbytes stored in each file */ +static _Atomic bool fsel_stop = false; +static pthread_t fsel_producer_thread; + static int fsel_path_index(const char *path) { @@ -61,6 +65,15 @@ static int fsel_path_index(const char *path) return ch <= '9' ? ch - '0' : ch - 'A' + 10; } +static void fsel_destroy(void *private_data) +{ + (void)private_data; + + fsel_stop = true; + + pthread_join(fsel_producer_thread, NULL); +} + static int fsel_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi) { @@ -205,6 +218,7 @@ static int fsel_poll(const char *path, struct fuse_file_info *fi, } static const struct fuse_operations fsel_oper = { + .destroy = fsel_destroy, .getattr = fsel_getattr, .readdir = fsel_readdir, .open = fsel_open, @@ -220,7 +234,7 @@ static void *fsel_producer(void *data) (void) data; - while (1) { + while (!fsel_stop) { int i, t; pthread_mutex_lock(&fsel_mutex); @@ -263,7 +277,6 @@ static void *fsel_producer(void *data) int main(int argc, char *argv[]) { - pthread_t producer; pthread_attr_t attr; int ret; @@ -279,7 +292,7 @@ int main(int argc, char *argv[]) return 1; } - errno = pthread_create(&producer, &attr, fsel_producer, NULL); + errno = pthread_create(&fsel_producer_thread, &attr, fsel_producer, NULL); if (errno) { perror("pthread_create"); return 1; @@ -287,8 +300,5 @@ int main(int argc, char *argv[]) ret = fuse_main(argc, argv, &fsel_oper, NULL); - pthread_cancel(producer); - pthread_join(producer, NULL); - return ret; } |