commit 8397f83add4009820ed2566a791a70fa7c022ae7 Author: overweight <5324761+overweight@user.noreply.gitee.com> Date: Mon Sep 30 10:39:10 2019 -0400 Package init diff --git a/0015-libfuse-fix-fs-cleanup.patch b/0015-libfuse-fix-fs-cleanup.patch new file mode 100644 index 0000000..b7616fb --- /dev/null +++ b/0015-libfuse-fix-fs-cleanup.patch @@ -0,0 +1,16 @@ +--- a/libfuse-fuse-2.9.7/lib/fuse.c 2019-04-18 22:50:35.628000000 +0800 ++++ b/libfuse-fuse-2.9.7/lib/fuse_1.c 2019-04-18 22:52:07.772000000 +0800 +@@ -4778,10 +4778,9 @@ out_free_name_table: + out_free_session: + fuse_session_destroy(f->se); + out_free_fs: +- /* Horrible compatibility hack to stop the destructor from being +- called on the filesystem without init being called first */ +- fs->op.destroy = NULL; +- fuse_fs_destroy(f->fs); ++ if (f->fs->m) ++ fuse_put_module(f->fs->m); ++ free(f->fs); + free(f->conf.modules); + f->conf.modules = NULL; + out_free: diff --git a/0032-fuse_opt_parse-fix-memory-leak.patch b/0032-fuse_opt_parse-fix-memory-leak.patch new file mode 100644 index 0000000..d71ce73 --- /dev/null +++ b/0032-fuse_opt_parse-fix-memory-leak.patch @@ -0,0 +1,53 @@ +From a38722be2ba63466431616a0756981697d29fa23 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Mon, 18 Feb 2013 16:24:11 +0100 +Subject: [PATCH 032/617] fuse_opt_parse(): fix memory leak + +when storing a newly allocated string for format "%s", free the previous value +stored at that location. + +Reported by Marco Schuster +--- + ChangeLog | 6 ++++++ + include/fuse_opt.h | 5 +++-- + lib/fuse_opt.c | 4 +++- + 3 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/libfuse-fuse-2.9.7/include/fuse_opt.h b/libfuse-fuse-2.9.7/include/fuse_opt.h +index add0a30..20653b1 100644 +--- a/libfuse-fuse-2.9.7/include/fuse_opt.h ++++ b/libfuse-fuse-2.9.7/include/fuse_opt.h +@@ -70,8 +70,9 @@ extern "C" { + * + * 6) "-x %s", etc. Combination of 4) and 5) + * +- * If the format is "%s", memory is allocated for the string unlike +- * with scanf(). ++ * If the format is "%s", memory is allocated for the string unlike with ++ * scanf(). The previous value (if non-NULL) stored at the this location is ++ * freed. + */ + struct fuse_opt { + /** Matching template and optional parameter formatting */ +diff --git a/libfuse-fuse-2.9.7/lib/fuse_opt.c b/libfuse-fuse-2.9.7/lib/fuse_opt.c +index 93efd29..15f9e21 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_opt.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_opt.c +@@ -204,11 +204,13 @@ static int process_opt_param(void *var, const char *format, const char *param, + { + assert(format[0] == '%'); + if (format[1] == 's') { ++ char **s = var; + char *copy = strdup(param); + if (!copy) + return alloc_failed(); + +- *(char **) var = copy; ++ free(*s); ++ *s = copy; + } else { + if (sscanf(param, format, var) != 1) { + fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg); +-- +1.8.3.1 + diff --git a/0530-fusermount-refuse-unknown-options.patch b/0530-fusermount-refuse-unknown-options.patch new file mode 100644 index 0000000..17e12f4 --- /dev/null +++ b/0530-fusermount-refuse-unknown-options.patch @@ -0,0 +1,43 @@ +From 5018a0c016495155ee598b7e0167b43d5d902414 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Sat, 14 Jul 2018 03:47:50 -0700 +Subject: [PATCH 530/617] fusermount: refuse unknown options + +Blacklists are notoriously fragile; especially if the kernel wishes to add +some security-critical mount option at a later date, all existing systems +with older versions of fusermount installed will suddenly have a security +problem. +Additionally, if the kernel's option parsing became a tiny bit laxer, the +blacklist could probably be bypassed. + +Whitelist known-harmless flags instead, even if it's slightly more +inconvenient. +--- + util/fusermount.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/util/fusermount.c b/util/fusermount.c +index 4e0f51a..2792407 100644 +--- a/util/fusermount.c ++++ b/util/fusermount.c +@@ -819,10 +819,16 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode, + flags |= flag; + else + flags &= ~flag; +- } else { ++ } else if (opt_eq(s, len, "default_permissions") || ++ opt_eq(s, len, "allow_other") || ++ begins_with(s, "max_read=") || ++ begins_with(s, "blksize=")) { + memcpy(d, s, len); + d += len; + *d++ = ','; ++ } else { ++ fprintf(stderr, "%s: unknown option '%.*s'\n", progname, len, s); ++ exit(1); + } + } + } +-- +1.8.3.1 + diff --git a/0531-fusermount-whitelist-known-good-filesystems-for-moun.patch b/0531-fusermount-whitelist-known-good-filesystems-for-moun.patch new file mode 100644 index 0000000..6afc82f --- /dev/null +++ b/0531-fusermount-whitelist-known-good-filesystems-for-moun.patch @@ -0,0 +1,121 @@ +From 795ad5d77434f3502e63a70c8a3fda94fa347e3d Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Sat, 14 Jul 2018 13:37:41 +0200 +Subject: [PATCH 531/617] fusermount: whitelist known-good filesystems for + mountpoints + +Before: + +$ _FUSE_COMMFD=1 priv_strace -s8000 -e trace=mount util/fusermount3 /proc/self/fd +mount("/dev/fuse", ".", "fuse", MS_NOSUID|MS_NODEV, "fd=3,rootmode=40000,user_id=379777,group_id=5001") = 0 +sending file descriptor: Socket operation on non-socket ++++ exited with 1 +++ + +After: + +$ _FUSE_COMMFD=1 priv_strace -s8000 -e trace=mount util/fusermount3 /proc/self/fd +util/fusermount3: mounting over filesystem type 0x009fa0 is forbidden ++++ exited with 1 +++ + +This patch could potentially have security +impact on some systems that are configured with allow_other; +see https://launchpad.net/bugs/1530566 for an example of how a similar +issue in the ecryptfs mount helper was exploitable. However, the FUSE +mount helper performs slightly different security checks, so that exact +attack doesn't work with fusermount; I don't know of any specific attack +you could perform using this, apart from faking the SELinux context of your +process when someone's looking at a process listing. Potential targets for +overwrite are (looking on a system with a 4.9 kernel): + +writable only for the current process: +/proc/self/{fd,map_files} +(Yes, "ls -l" claims that you don't have write access, but that's not true; +"find -writable" will show you what access you really have.) + +writable also for other owned processes: +/proc/$pid/{sched,autogroup,comm,mem,clear_refs,attr/*,oom_adj, +oom_score_adj,loginuid,coredump_filter,uid_map,gid_map,projid_map, +setgroups,timerslack_ns} +--- + util/fusermount.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 49 insertions(+), 1 deletion(-) + +diff --git a/libfuse-fuse-2.9.7/util/fusermount.c b/libfuse-fuse-2.9.7/util/fusermount.c +index 2792407..c63c50e 100644 +--- a/libfuse-fuse-2.9.7/util/fusermount.c ++++ b/libfuse-fuse-2.9.7/util/fusermount.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #define FUSE_COMMFD_ENV "_FUSE_COMMFD" + +@@ -915,6 +916,8 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd) + int res; + const char *mnt = *mntp; + const char *origmnt = mnt; ++ struct statfs fs_buf; ++ size_t i; + + res = lstat(mnt, stbuf); + if (res == -1) { +@@ -987,8 +990,53 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd) + return -1; + } + ++ /* Do not permit mounting over anything in procfs - it has a couple ++ * places to which we have "write access" without being supposed to be ++ * able to just put anything we want there. ++ * Luckily, without allow_other, we can't get other users to actually ++ * use any fake information we try to put there anyway. ++ * Use a whitelist to be safe. */ ++ if (statfs(*mntp, &fs_buf)) { ++ fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", ++ progname, mnt, strerror(errno)); ++ return -1; ++ } + +- return 0; ++ /* Use the same list of permitted filesystems for the mount target as ++ * the ecryptfs mount helper ++ * (https://bazaar.launchpad.net/~ecryptfs/ecryptfs/trunk/view/head:/src/utils/mount.ecryptfs_private.c#L225). */ ++ typeof(fs_buf.f_type) f_type_whitelist[] = { ++ 0x61756673 /* AUFS_SUPER_MAGIC */, ++ 0x9123683E /* BTRFS_SUPER_MAGIC */, ++ 0x00C36400 /* CEPH_SUPER_MAGIC */, ++ 0xFF534D42 /* CIFS_MAGIC_NUMBER */, ++ 0x0000F15F /* ECRYPTFS_SUPER_MAGIC */, ++ 0x0000EF53 /* EXT[234]_SUPER_MAGIC */, ++ 0xF2F52010 /* F2FS_SUPER_MAGIC */, ++ 0x65735546 /* FUSE_SUPER_MAGIC */, ++ 0x01161970 /* GFS2_MAGIC */, ++ 0x3153464A /* JFS_SUPER_MAGIC */, ++ 0x000072B6 /* JFFS2_SUPER_MAGIC */, ++ 0x0000564C /* NCP_SUPER_MAGIC */, ++ 0x00006969 /* NFS_SUPER_MAGIC */, ++ 0x00003434 /* NILFS_SUPER_MAGIC */, ++ 0x5346544E /* NTFS_SB_MAGIC */, ++ 0x794C7630 /* OVERLAYFS_SUPER_MAGIC */, ++ 0x52654973 /* REISERFS_SUPER_MAGIC */, ++ 0x73717368 /* SQUASHFS_MAGIC */, ++ 0x01021994 /* TMPFS_MAGIC */, ++ 0x24051905 /* UBIFS_SUPER_MAGIC */, ++ 0x58465342 /* XFS_SB_MAGIC */, ++ 0x2FC12FC1 /* ZFS_SUPER_MAGIC */, ++ }; ++ for (i = 0; i < sizeof(f_type_whitelist)/sizeof(f_type_whitelist[0]); i++) { ++ if (f_type_whitelist[i] == fs_buf.f_type) ++ return 0; ++ } ++ ++ fprintf(stderr, "%s: mounting over filesystem type %#010lx is forbidden\n", ++ progname, (unsigned long)fs_buf.f_type); ++ return -1; + } + + static int try_open(const char *dev, char **devp, int silent) +-- +1.8.3.1 + diff --git a/0533-fusermount-Fix-memory-leaks.patch b/0533-fusermount-Fix-memory-leaks.patch new file mode 100644 index 0000000..1aab2a8 --- /dev/null +++ b/0533-fusermount-Fix-memory-leaks.patch @@ -0,0 +1,32 @@ +From efa3032bc9a6d9028084a8c33c9b31946b16aea1 Mon Sep 17 00:00:00 2001 +From: Rostislav Skudnov +Date: Sat, 21 Jul 2018 21:14:06 +0000 +Subject: [PATCH 533/617] fusermount: Fix memory leaks + +--- + util/fusermount.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/util/fusermount.c b/util/fusermount.c +index c63c50e..b8c164d 100644 +--- a/util/fusermount.c ++++ b/util/fusermount.c +@@ -446,6 +446,7 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) + } + + out: ++ free(copy); + if (res == -1) + return -1; + +@@ -1365,6 +1366,7 @@ do_unmount: + } + if (res == -1) + goto err_out; ++ free(mnt); + return 0; + + err_out: +-- +1.8.3.1 + diff --git a/0545-Fix-invalid-free-of-memory-pointer-in-struct-fuse_bu.patch b/0545-Fix-invalid-free-of-memory-pointer-in-struct-fuse_bu.patch new file mode 100644 index 0000000..d61af31 --- /dev/null +++ b/0545-Fix-invalid-free-of-memory-pointer-in-struct-fuse_bu.patch @@ -0,0 +1,27 @@ +From f814b4fa0b1a3b0d377effafe6c473745baea04b Mon Sep 17 00:00:00 2001 +From: Rostislav +Date: Sat, 25 Aug 2018 18:52:53 +0000 +Subject: [PATCH 545/617] Fix invalid free of memory pointer in 'struct + fuse_buf' + +--- + lib/fuse.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/fuse.c b/lib/fuse.c +index 2e4505b..11ffc05 100644 +--- a/lib/fuse.c ++++ b/lib/fuse.c +@@ -1760,7 +1760,8 @@ static void fuse_free_buf(struct fuse_bufvec *buf) + size_t i; + + for (i = 0; i < buf->count; i++) +- free(buf->buf[i].mem); ++ if (!(buf->buf[0].flags & FUSE_BUF_IS_FD)) ++ free(buf->buf[i].mem); + free(buf); + } + } +-- +1.8.3.1 + diff --git a/0546-Fix-memory-leak-of-FUSE-modules.patch b/0546-Fix-memory-leak-of-FUSE-modules.patch new file mode 100644 index 0000000..a77c289 --- /dev/null +++ b/0546-Fix-memory-leak-of-FUSE-modules.patch @@ -0,0 +1,76 @@ +From 82ee6d6f77a2e386e42714d6ab56b39fcb00488e Mon Sep 17 00:00:00 2001 +From: Rostislav +Date: Sat, 25 Aug 2018 20:50:40 +0000 +Subject: [PATCH 546/617] Fix memory leak of FUSE modules + +--- + lib/fuse.c | 26 +++++++++++++++++++++++--- + 1 file changed, 23 insertions(+), 3 deletions(-) + +diff --git a/lib/fuse.c b/lib/fuse.c +index 11ffc05..b88ef1a 100644 +--- a/lib/fuse.c ++++ b/lib/fuse.c +@@ -234,6 +234,18 @@ static int fuse_register_module(const char *name, + return 0; + } + ++static void fuse_unregister_module(struct fuse_module *m) ++{ ++ struct fuse_module **mp; ++ for (mp = &fuse_modules; *mp; mp = &(*mp)->next) { ++ if (*mp == m) { ++ *mp = (*mp)->next; ++ break; ++ } ++ } ++ free(m->name); ++ free(m); ++} + + static int fuse_load_so_module(const char *module) + { +@@ -313,8 +325,11 @@ static struct fuse_module *fuse_get_module(const char *module) + static void fuse_put_module(struct fuse_module *m) + { + pthread_mutex_lock(&fuse_context_lock); +- assert(m->ctr > 0); +- m->ctr--; ++ if (m->so) ++ assert(m->ctr > 0); ++ /* Builtin modules may already have m->ctr == 0 */ ++ if (m->ctr > 0) ++ m->ctr--; + if (!m->ctr && m->so) { + struct fusemod_so *so = m->so; + assert(so->ctr > 0); +@@ -323,13 +338,15 @@ static void fuse_put_module(struct fuse_module *m) + struct fuse_module **mp; + for (mp = &fuse_modules; *mp;) { + if ((*mp)->so == so) +- *mp = (*mp)->next; ++ fuse_unregister_module(*mp); + else + mp = &(*mp)->next; + } + dlclose(so->handle); + free(so); + } ++ } else if (!m->ctr) { ++ fuse_unregister_module(m); + } + pthread_mutex_unlock(&fuse_context_lock); + } +@@ -4962,6 +4979,9 @@ void fuse_destroy(struct fuse *f) + assert(list_empty(&f->partial_slabs)); + assert(list_empty(&f->full_slabs)); + ++ while (fuse_modules) { ++ fuse_put_module(fuse_modules); ++ } + free(f->id_table.array); + free(f->name_table.array); + pthread_mutex_destroy(&f->lock); +-- +1.8.3.1 + diff --git a/CVE-2018-10906.patch b/CVE-2018-10906.patch new file mode 100644 index 0000000..56b7f68 --- /dev/null +++ b/CVE-2018-10906.patch @@ -0,0 +1,55 @@ +From 453a5451f20f22cb466b5be58f7d771ca5fa6d25 Mon Sep 17 00:00:00 2001 +From: gulining +Date: Fri, 22 Mar 2019 02:23:47 -0400 +Subject: [PATCH] backport-CVE-2018-10906.patch + +Signed-off-by: gulining +--- + libfuse-fuse-2.9.7/util/fusermount.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/libfuse-fuse-2.9.7/util/fusermount.c b/libfuse-fuse-2.9.7/util/fusermount.c +index d950c5c..e14e7dd 100644 +--- a/libfuse-fuse-2.9.7/util/fusermount.c ++++ b/libfuse-fuse-2.9.7/util/fusermount.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #define FUSE_COMMFD_ENV "_FUSE_COMMFD" + +@@ -740,8 +741,10 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode, + unsigned len; + const char *fsname_str = "fsname="; + const char *subtype_str = "subtype="; ++ bool escape_ok = begins_with(s, fsname_str) || ++ begins_with(s, subtype_str); + for (len = 0; s[len]; len++) { +- if (s[len] == '\\' && s[len + 1]) ++ if (escape_ok && s[len] == '\\' && s[len + 1]) + len++; + else if (s[len] == ',') + break; +@@ -795,10 +798,16 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode, + flags |= flag; + else + flags &= ~flag; +- } else { ++ } else if (opt_eq(s, len, "default_permissions") || ++ opt_eq(s, len, "allow_other") || ++ begins_with(s, "max_read=") || ++ begins_with(s, "blksize=")) { + memcpy(d, s, len); + d += len; + *d++ = ','; ++ } else { ++ fprintf(stderr, "%s: unknown option '%.*s'\n", progname, len, s); ++ exit(1); + } + } + } +-- +1.8.3.1 + diff --git a/bugfix-increase-idle-thread.patch b/bugfix-increase-idle-thread.patch new file mode 100644 index 0000000..472e250 --- /dev/null +++ b/bugfix-increase-idle-thread.patch @@ -0,0 +1,200 @@ +From 4028ca2038bab675b8464b71e038c28adfdb739f Mon Sep 17 00:00:00 2001 +From: +Date: Wed, 5 Sep 2018 21:27:38 +0800 +Subject: [PATCH] increase idle thread + +Signed-off-by: +--- + libfuse-fuse-2.9.7/lib/fuse.c | 8 ++++++-- + libfuse-fuse-2.9.7/lib/fuse_kern_chan.c | 6 +++++- + libfuse-fuse-2.9.7/lib/fuse_loop_mt.c | 9 ++++++++- + libfuse-fuse-2.9.7/lib/fuse_lowlevel.c | 26 +++++++++++++++++++------- + 4 files changed, 38 insertions(+), 11 deletions(-) + +diff --git a/libfuse-fuse-2.9.7/lib/fuse.c b/libfuse-fuse-2.9.7/lib/fuse.c +index 6a7c307..9f8c8a2 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse.c ++++ b/libfuse-fuse-2.9.7/lib/fuse.c +@@ -1261,6 +1261,7 @@ static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid, + wake_up_queued(f); + pthread_mutex_unlock(&f->lock); + free(path); ++ path = NULL; + } + + static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path) +@@ -3085,8 +3086,11 @@ static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path, + + pthread_mutex_lock(&f->lock); + node = get_node(f, ino); +- assert(node->open_count > 0); +- --node->open_count; ++ if (node->open_count > 0) { ++ --node->open_count; ++ } else { ++ fprintf(stderr, "fuse: open_count is invalid: %d\n", node->open_count); ++ } + if (node->is_hidden && !node->open_count) { + unlink_hidden = 1; + node->is_hidden = 0; +diff --git a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +index 4cc9b73..b891568 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +@@ -30,7 +30,9 @@ restart: + + if (fuse_session_exited(se)) + return 0; ++ + if (res == -1) { ++ perror("fuse: read from chan error"); + /* ENOENT means the operation was interrupted, it's safe + to restart */ + if (err == ENOENT) +diff --git a/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c b/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c +index 2f2521f..f88f339 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c +@@ -121,7 +121,7 @@ static void *fuse_do_work(void *data) + pthread_mutex_lock(&mt->lock); + if (!isforget) + mt->numavail++; +- if (mt->numavail > 10) { ++ if (mt->numavail > 20) { + if (mt->exit) { + pthread_mutex_unlock(&mt->lock); + return NULL; +@@ -133,7 +133,9 @@ static void *fuse_do_work(void *data) + + pthread_detach(w->thread_id); + free(w->buf); ++ w->buf = NULL; + free(w); ++ w = NULL; + return NULL; + } + pthread_mutex_unlock(&mt->lock); +@@ -229,13 +231,16 @@ static int fuse_loop_start_thread(struct fuse_mt *mt) + if (!w->buf) { + fprintf(stderr, "fuse: failed to allocate read buffer\n"); + free(w); ++ w = NULL; + return -1; + } + + res = fuse_start_thread(&w->thread_id, fuse_do_work, w); + if (res == -1) { + free(w->buf); ++ w->buf = NULL; + free(w); ++ w = NULL; + return -1; + } + list_add_worker(w, &mt->main); +@@ -252,7 +257,9 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w) + list_del_worker(w); + pthread_mutex_unlock(&mt->lock); + free(w->buf); ++ w->buf = NULL; + free(w); ++ w = NULL; + } + + int fuse_session_loop_mt(struct fuse_session *se) +diff --git a/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c b/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c +index 35d0204..4dda646 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c +@@ -42,8 +42,8 @@ + + struct fuse_pollhandle { + uint64_t kh; +- struct fuse_chan *ch; + struct fuse_ll *f; ++ struct fuse_session *se; + }; + + static size_t pagesize; +@@ -738,6 +738,7 @@ static int fuse_send_data_iov(struct fuse_ll *f, struct fuse_chan *ch, + return 0; + + clear_pipe: ++ perror("fuse: reach clear_pipe"); + fuse_ll_clear_pipe(f); + return res; + +@@ -1708,8 +1709,8 @@ static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) + return; + } + ph->kh = arg->kh; +- ph->ch = req->ch; + ph->f = req->f; ++ ph->se = fuse_chan_session(req->ch); + } + + req->f->op.poll(req, nodeid, &fi, ph); +@@ -1972,7 +1973,8 @@ int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph) + iov[1].iov_base = &outarg; + iov[1].iov_len = sizeof(outarg); + +- return send_notify_iov(ph->f, ph->ch, FUSE_NOTIFY_POLL, iov, 2); ++ return send_notify_iov(ph->f, ph->se->ch, ++ FUSE_NOTIFY_POLL, iov, 2); + } else { + return 0; + } +@@ -2342,6 +2344,7 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, + + res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv); + if (res < 0) ++ fprintf(stderr, "fuse: failed to copy from pipe\n"); + goto clear_pipe; + + in = mbuf; +@@ -2359,6 +2362,7 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, + + req = fuse_ll_alloc_req(f); + if (req == NULL) { ++ fprintf(stderr, "fuse: req is NULL\n"); + struct fuse_out_header out = { + .unique = in->unique, + .error = -ENOMEM, +@@ -2383,10 +2387,14 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, + enum fuse_opcode expected; + + expected = f->cuse_data ? CUSE_INIT : FUSE_INIT; +- if (in->opcode != expected) ++ if (in->opcode != expected) { ++ fprintf(stderr, "fuse: opcode is not as expected\n"); + goto reply_err; +- } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT) ++ } ++ } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT) { ++ fprintf(stderr, "fuse: opcode is *_INIT\n"); + goto reply_err; ++ } + + err = EACCES; + if (f->allow_root && in->uid != f->owner && in->uid != 0 && +@@ -2394,12 +2402,16 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, + in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && + in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && + in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR && +- in->opcode != FUSE_NOTIFY_REPLY) ++ in->opcode != FUSE_NOTIFY_REPLY) { ++ fprintf(stderr, "fuse: opcode is not allowed\n"); + goto reply_err; ++ } + + err = ENOSYS; +- if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func) ++ if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func) { ++ fprintf(stderr, "fuse: opcode is invalid\n"); + goto reply_err; ++ } + if (in->opcode != FUSE_INTERRUPT) { + struct fuse_req *intr; + pthread_mutex_lock(&f->lock); +-- +1.8.3.1 + diff --git a/bugfix-invalid-free-and-core.patch b/bugfix-invalid-free-and-core.patch new file mode 100644 index 0000000..059ebe4 --- /dev/null +++ b/bugfix-invalid-free-and-core.patch @@ -0,0 +1,131 @@ +From fd0cfd7fa7d37a8401c8544dfaac0172d1d35056 Mon Sep 17 00:00:00 2001 +From: +Date: Fri, 23 Nov 2018 17:14:22 +0800 +Subject: [PATCH] fuse: fix invalid free and core bug + +Signed-off-by: +--- + libfuse-fuse-2.9.7/lib/fuse.c | 3 ++- + libfuse-fuse-2.9.7/lib/fuse_kern_chan.c | 3 ++- + libfuse-fuse-2.9.7/lib/fuse_lowlevel.c | 26 ++++++++++++++++---------- + libfuse-fuse-2.9.7/util/fusermount.c | 1 + + 4 files changed, 21 insertions(+), 12 deletions(-) + +diff --git a/libfuse-fuse-2.9.7/lib/fuse.c b/libfuse-fuse-2.9.7/lib/fuse.c +index e7cda46..c40961d 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse.c ++++ b/libfuse-fuse-2.9.7/lib/fuse.c +@@ -1752,7 +1752,8 @@ static void fuse_free_buf(struct fuse_bufvec *buf) + size_t i; + + for (i = 0; i < buf->count; i++) +- free(buf->buf[i].mem); ++ if (!(buf->buf[0].flags & FUSE_BUF_IS_FD)) ++ free(buf->buf[i].mem); + free(buf); + } + } +diff --git a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +index b891568..70deb6f 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +@@ -64,6 +64,7 @@ static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[], + int err = errno; + + if (res == -1) { ++ perror("fuse: write to chan error"); + struct fuse_session *se = fuse_chan_session(ch); + + assert(se != NULL); +@@ -83,6 +83,7 @@ + close(fd); + } + ++#define KERNEL_BUF_PAGES 128 + #define MIN_BUFSIZE 0x21000 + + struct fuse_chan *fuse_kern_chan_new(int fd) +diff --git a/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c b/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c +index 4dda646..0d278cf 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c +@@ -2343,9 +2343,10 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, + tmpbuf.buf[0].mem = mbuf; + + res = fuse_ll_copy_from_pipe(&tmpbuf, &bufv); +- if (res < 0) ++ if (res < 0) { + fprintf(stderr, "fuse: failed to copy from pipe\n"); + goto clear_pipe; ++ } + + in = mbuf; + } else { +@@ -2403,13 +2404,13 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, + in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && + in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR && + in->opcode != FUSE_NOTIFY_REPLY) { +- fprintf(stderr, "fuse: opcode is not allowed\n"); +- goto reply_err; ++ fprintf(stderr, "fuse: opcode is not allowed\n"); ++ goto reply_err; + } + + err = ENOSYS; + if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func) { +- fprintf(stderr, "fuse: opcode is invalid\n"); ++ fprintf(stderr, "fuse: opcode is invalid %d\n", in->opcode); + goto reply_err; + } + if (in->opcode != FUSE_INTERRUPT) { +@@ -2599,12 +2600,15 @@ static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, + int err; + int res; + +- if (f->conn.proto_minor < 14 || !(f->conn.want & FUSE_CAP_SPLICE_READ)) ++ if (f->conn.proto_minor < 14 || !(f->conn.want & FUSE_CAP_SPLICE_READ)) { + goto fallback; ++ } + + llp = fuse_ll_get_pipe(f); +- if (llp == NULL) ++ if (llp == NULL) { ++ perror("fuse: failed to get pipe"); + goto fallback; ++ } + + if (llp->size < bufsize) { + if (llp->can_grow) { +@@ -2668,11 +2672,13 @@ static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf, + fuse_ll_clear_pipe(f); + return -EIO; + } +- buf->size = tmpbuf.size; +- return buf->size; ++ assert(res == tmpbuf.size); ++ } else { ++ /* Don't overwrite buf->mem, as that would cause a leak */ ++ buf->fd = tmpbuf.fd; ++ buf->flags = tmpbuf.flags; + } +- +- *buf = tmpbuf; ++ buf->size = tmpbuf.size; + + return res; + +diff --git a/libfuse-fuse-2.9.7/util/fusermount.c b/libfuse-fuse-2.9.7/util/fusermount.c +index 265f55a..832ba2a 100644 +--- a/libfuse-fuse-2.9.7/util/fusermount.c ++++ b/libfuse-fuse-2.9.7/util/fusermount.c +@@ -446,6 +446,7 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) + } + + out: ++ free(copy); + if (res == -1) + return -1; + +-- +1.8.3.1 + diff --git a/bugfix-memory-leak-and-wild-ptr.patch b/bugfix-memory-leak-and-wild-ptr.patch new file mode 100644 index 0000000..760cd67 --- /dev/null +++ b/bugfix-memory-leak-and-wild-ptr.patch @@ -0,0 +1,530 @@ +From 276380d842ea9f57f181fc8f37d268d619a753eb Mon Sep 17 00:00:00 2001 +From: +Date: Sat, 1 Dec 2018 11:35:08 +0800 +Subject: [PATCH] fix memory leak and wild ptr + +Signed-off-by: +--- + libfuse-fuse-2.9.7/lib/fuse.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++---- + libfuse-fuse-2.9.7/lib/fuse_kern_chan.c | 5 ++++- + libfuse-fuse-2.9.7/lib/fuse_loop_mt.c | 1 + + libfuse-fuse-2.9.7/lib/fuse_lowlevel.c | 28 ++++++++++++++++++++++++++- + 4 files changed, 81 insertions(+), 6 deletions(-) + +diff --git a/libfuse-fuse-2.9.7/lib/fuse.c b/libfuse-fuse-2.9.7/lib/fuse.c +index c40961d..05ee145 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse.c ++++ b/libfuse-fuse-2.9.7/lib/fuse.c +@@ -252,6 +252,7 @@ err: + if (so->handle) + dlclose(so->handle); + free(so); ++ so = NULL; + return -1; + } + +@@ -266,6 +267,7 @@ static int fuse_load_so_module(const char *module) + sprintf(soname, "libfusemod_%s.so", module); + res = fuse_load_so_name(soname); + free(soname); ++ soname = NULL; + return res; + } + +@@ -315,6 +317,7 @@ static void fuse_put_module(struct fuse_module *m) + } + dlclose(so->handle); + free(so); ++ so = NULL; + } + } + pthread_mutex_unlock(&fuse_context_lock); +@@ -479,6 +482,7 @@ static void free_node_mem(struct fuse *f, struct node *node) + { + (void) f; + free(node); ++ node = NULL; + } + #endif + +@@ -538,8 +542,10 @@ static void set_forget_time(struct fuse *f, struct node *node) + + static void free_node(struct fuse *f, struct node *node) + { +- if (node->name != node->inline_name) ++ if (node->name != node->inline_name) { + free(node->name); ++ node->name = NULL; ++ } + free_node_mem(f, node); + } + +@@ -713,9 +719,10 @@ static void unhash_name(struct fuse *f, struct node *node) + *nodep = node->name_next; + node->name_next = NULL; + unref_node(f, node->parent); +- if (node->name != node->inline_name) ++ if (node->name != node->inline_name) { + free(node->name); +- node->name = NULL; ++ node->name = NULL; ++ } + node->parent = NULL; + f->name_table.use--; + +@@ -1009,6 +1016,7 @@ static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name, + unlock_path(f, nodeid, wnode, node); + out_free: + free(buf); ++ buf = NULL; + + out_err: + return err; +@@ -1216,6 +1224,7 @@ static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1, + + unlock_path(f, nodeid1, wn1, NULL); + free(*path1); ++ *path1 = NULL; + } + } + return err; +@@ -1282,7 +1291,9 @@ static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2, + wake_up_queued(f); + pthread_mutex_unlock(&f->lock); + free(path1); ++ path1 = NULL; + free(path2); ++ path2 = NULL; + } + + static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup) +@@ -1752,9 +1763,12 @@ static void fuse_free_buf(struct fuse_bufvec *buf) + size_t i; + + for (i = 0; i < buf->count; i++) +- if (!(buf->buf[0].flags & FUSE_BUF_IS_FD)) ++ if (!(buf->buf[0].flags & FUSE_BUF_IS_FD)) { + free(buf->buf[i].mem); ++ buf->buf[i].mem = NULL; ++ } + free(buf); ++ buf = NULL; + } + } + +@@ -1785,6 +1799,7 @@ int fuse_fs_read_buf(struct fuse_fs *fs, const char *path, + mem = malloc(size); + if (mem == NULL) { + free(buf); ++ buf = NULL; + return -ENOMEM; + } + *buf = FUSE_BUFVEC_INIT(size); +@@ -1879,6 +1894,7 @@ int fuse_fs_write_buf(struct fuse_fs *fs, const char *path, + off, fi); + out_free: + free(mem); ++ mem = NULL; + } + out: + if (fs->debug && res >= 0) +@@ -2418,6 +2434,7 @@ static int hide_node(struct fuse *f, const char *oldpath, + if (!err) + err = rename_node(f, dir, oldname, dir, newname, 1); + free(newpath); ++ newpath = NULL; + } + return err; + } +@@ -2517,6 +2534,7 @@ static struct fuse_context_i *fuse_get_context_internal(void) + static void fuse_freecontext(void *data) + { + free(data); ++ data = NULL; + } + + static int fuse_create_context_key(void) +@@ -2613,6 +2631,7 @@ void fuse_fs_destroy(struct fuse_fs *fs) + if (fs->m) + fuse_put_module(fs->m); + free(fs); ++ fs = NULL; + } + + static void fuse_lib_destroy(void *data) +@@ -3360,11 +3379,13 @@ static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino, + fuse_fs_releasedir(f->fs, path, &fi); + pthread_mutex_destroy(&dh->lock); + free(dh); ++ dh = NULL; + } + } else { + reply_err(req, err); + pthread_mutex_destroy(&dh->lock); + free(dh); ++ dh = NULL; + } + free_path(f, ino, path); + } +@@ -3536,7 +3557,9 @@ static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino, + pthread_mutex_unlock(&dh->lock); + pthread_mutex_destroy(&dh->lock); + free(dh->contents); ++ dh->contents = NULL; + free(dh); ++ dh = NULL; + reply_err(req, 0); + } + +@@ -3639,6 +3662,7 @@ static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, + else + reply_err(req, res); + free(value); ++ value = NULL; + } else { + res = common_getxattr(f, req, ino, name, NULL, 0); + if (res >= 0) +@@ -3682,6 +3706,7 @@ static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) + else + reply_err(req, res); + free(list); ++ list = NULL; + } else { + res = common_listxattr(f, req, ino, NULL, 0); + if (res >= 0) +@@ -3727,6 +3752,7 @@ static void delete_lock(struct lock **lockp) + struct lock *l = *lockp; + *lockp = l->next; + free(l); ++ l = NULL; + } + + static void insert_lock(struct lock **pos, struct lock *lock) +@@ -3748,7 +3774,9 @@ static int locks_insert(struct node *node, struct lock *lock) + + if (!newl1 || !newl2) { + free(newl1); ++ newl1 = NULL; + free(newl2); ++ newl2 = NULL; + return -ENOLCK; + } + } +@@ -3805,7 +3833,9 @@ static int locks_insert(struct node *node, struct lock *lock) + } + out: + free(newl1); ++ newl1 = NULL; + free(newl2); ++ newl2 = NULL; + return 0; + } + +@@ -4042,6 +4072,7 @@ err: + reply_err(req, err); + out: + free(out_buf); ++ out_buf = NULL; + } + + static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino, +@@ -4189,7 +4220,9 @@ int fuse_notify_poll(struct fuse_pollhandle *ph) + static void free_cmd(struct fuse_cmd *cmd) + { + free(cmd->buf); ++ cmd->buf = NULL; + free(cmd); ++ cmd = NULL; + } + + void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) +@@ -4219,6 +4252,7 @@ static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize) + if (cmd->buf == NULL) { + fprintf(stderr, "fuse: failed to allocate read buffer\n"); + free(cmd); ++ cmd = NULL; + return NULL; + } + return cmd; +@@ -4301,6 +4335,7 @@ static int fuse_session_loop_remember(struct fuse *f) + } + + free(buf); ++ buf = NULL; + fuse_session_reset(se); + return res < 0 ? -1 : 0; + } +@@ -4719,10 +4754,13 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, + + out_free_root: + free(root); ++ root = NULL; + out_free_id_table: + free(f->id_table.array); ++ f->id_table.array = NULL; + out_free_name_table: + free(f->name_table.array); ++ f->name_table.array = NULL; + out_free_session: + fuse_session_destroy(f->se); + out_free_fs: +@@ -4731,8 +4769,10 @@ out_free_fs: + fs->op.destroy = NULL; + fuse_fs_destroy(f->fs); + free(f->conf.modules); ++ f->conf.modules = NULL; + out_free: + free(f); ++ f = NULL; + out_delete_context_key: + fuse_delete_context_key(); + out: +@@ -4769,6 +4809,7 @@ void fuse_destroy(struct fuse *f) + if (try_get_path(f, node->nodeid, NULL, &path, NULL, false) == 0) { + fuse_fs_unlink(f->fs, path); + free(path); ++ path = NULL; + } + } + } +@@ -4788,11 +4829,15 @@ void fuse_destroy(struct fuse *f) + assert(list_empty(&f->full_slabs)); + + free(f->id_table.array); ++ f->id_table.array = NULL; + free(f->name_table.array); ++ f->name_table.array = NULL; + pthread_mutex_destroy(&f->lock); + fuse_session_destroy(f->se); + free(f->conf.modules); ++ f->conf.modules = NULL; + free(f); ++ f = NULL; + fuse_delete_context_key(); + } + +diff --git a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +index 70deb6f..1096fa3 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +@@ -26,6 +26,9 @@ static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf, + + restart: + res = read(fuse_chan_fd(ch), buf, size); ++ if (res >= size) { ++ fprintf(stderr, "fuse: read %d from chan, risk to leak memory\n", res); ++ } + err = errno; + + if (fuse_session_exited(se)) +@@ -85,7 +88,7 @@ + close(fd); + } + +-#define KERNEL_BUF_PAGES 128 ++#define KERNEL_BUF_PAGES 32 + #define MIN_BUFSIZE 0x21000 + + struct fuse_chan *fuse_kern_chan_new(int fd) +diff --git a/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c b/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c +index ea92b62..eca39b1 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_loop_mt.c +@@ -71,6 +71,7 @@ static void *fuse_do_work(void *data) + while (!fuse_session_exited(mt->se)) { + int isforget = 0; + struct fuse_chan *ch = mt->prevch; ++ memset(w->buf, 0, w->bufsize); + struct fuse_buf fbuf = { + .mem = w->buf, + .size = w->bufsize, +diff --git a/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c b/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c +index 0d278cf..b4ed46d 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_lowlevel.c +@@ -121,6 +121,7 @@ static void destroy_req(fuse_req_t req) + { + pthread_mutex_destroy(&req->lock); + free(req); ++ req = NULL; + } + + void fuse_free_req(fuse_req_t req) +@@ -237,6 +238,7 @@ int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) + + res = send_reply_iov(req, 0, padded_iov, count); + free(padded_iov); ++ padded_iov = NULL; + + return res; + } +@@ -458,6 +460,7 @@ static int fuse_send_data_iov_fallback(struct fuse_ll *f, struct fuse_chan *ch, + res = fuse_buf_copy(&mem_buf, buf, 0); + if (res < 0) { + free(mbuf); ++ mbuf = NULL; + return -res; + } + len = res; +@@ -467,6 +470,7 @@ static int fuse_send_data_iov_fallback(struct fuse_ll *f, struct fuse_chan *ch, + iov_count++; + res = fuse_send_msg(f, ch, iov, iov_count); + free(mbuf); ++ mbuf = NULL; + + return res; + } +@@ -482,6 +486,7 @@ static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp) + close(llp->pipe[0]); + close(llp->pipe[1]); + free(llp); ++ llp = NULL; + } + + #ifdef HAVE_SPLICE +@@ -498,6 +503,7 @@ static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f) + res = pipe(llp->pipe); + if (res == -1) { + free(llp); ++ llp = NULL; + return NULL; + } + +@@ -506,6 +512,7 @@ static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f) + close(llp->pipe[0]); + close(llp->pipe[1]); + free(llp); ++ llp = NULL; + return NULL; + } + +@@ -683,18 +690,22 @@ static int fuse_send_data_iov(struct fuse_ll *f, struct fuse_chan *ch, + tmpbuf = malloc(headerlen); + if (tmpbuf == NULL) { + free(mbuf); ++ mbuf = NULL; + res = ENOMEM; + goto clear_pipe; + } + res = read_back(llp->pipe[0], tmpbuf, headerlen); + free(tmpbuf); ++ tmpbuf = NULL; + if (res != 0) { + free(mbuf); ++ mbuf = NULL; + goto clear_pipe; + } + res = read_back(llp->pipe[0], mbuf, now_len); + if (res != 0) { + free(mbuf); ++ mbuf = NULL; + goto clear_pipe; + } + len = now_len + extra_len; +@@ -703,9 +714,11 @@ static int fuse_send_data_iov(struct fuse_ll *f, struct fuse_chan *ch, + iov_count++; + res = fuse_send_msg(f, ch, iov, iov_count); + free(mbuf); ++ mbuf = NULL; + return res; + } + free(mbuf); ++ mbuf = NULL; + res = now_len; + } + len = res; +@@ -907,7 +920,9 @@ int fuse_reply_ioctl_retry(fuse_req_t req, + res = send_reply_iov(req, 0, iov, count); + out: + free(in_fiov); ++ in_fiov = NULL; + free(out_fiov); ++ out_fiov = NULL; + + return res; + +@@ -957,6 +972,7 @@ int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, + + res = send_reply_iov(req, 0, padded_iov, count + 2); + free(padded_iov); ++ padded_iov = NULL; + + return res; + } +@@ -1633,6 +1649,7 @@ static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req) + req->interrupted = 1; + list_del_req(curr); + free(curr); ++ curr = NULL; + return NULL; + } + } +@@ -1688,6 +1705,7 @@ static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) + void fuse_pollhandle_destroy(struct fuse_pollhandle *ph) + { + free(ph); ++ ph = NULL; + } + + static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +@@ -2141,6 +2159,7 @@ static void fuse_ll_retrieve_reply(struct fuse_notify_req *nreq, + } + out: + free(rreq); ++ rreq = NULL; + if ((ibuf->flags & FUSE_BUF_IS_FD) && bufv.idx < bufv.count) + fuse_ll_clear_pipe(f); + } +@@ -2189,6 +2208,7 @@ int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino, + list_del_nreq(&rreq->nreq); + pthread_mutex_unlock(&f->lock); + free(rreq); ++ rreq = NULL; + } + + return err; +@@ -2455,6 +2475,7 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf, + + out_free: + free(mbuf); ++ mbuf = NULL; + return; + + reply_err: +@@ -2579,7 +2600,9 @@ static void fuse_ll_destroy(void *data) + pthread_key_delete(f->pipe_key); + pthread_mutex_destroy(&f->lock); + free(f->cuse_data); ++ f->cuse_data = NULL; + free(f); ++ f = NULL; + } + + static void fuse_ll_pipe_destructor(void *data) +@@ -2777,6 +2800,7 @@ out_key_destroy: + out_free: + pthread_mutex_destroy(&f->lock); + free(f); ++ f = NULL; + out: + return NULL; + } +@@ -2821,6 +2845,7 @@ retry: + + if (ret == bufsize) { + free(buf); ++ buf = NULL; + bufsize *= 4; + goto retry; + } +@@ -2846,6 +2871,7 @@ retry: + + out_free: + free(buf); ++ buf = NULL; + return ret; + } + #else /* linux */ +-- +1.8.3.1 + diff --git a/fix-fuse-crash-problem-when-rm-node.patch b/fix-fuse-crash-problem-when-rm-node.patch new file mode 100644 index 0000000..0c869ea --- /dev/null +++ b/fix-fuse-crash-problem-when-rm-node.patch @@ -0,0 +1,34 @@ +From a17e9cd2c332084092888b3ee67a891ebcba2ac6 Mon Sep 17 00:00:00 2001 +From: Shijie Luo +Date: Tue, 23 Jul 2019 19:12:56 +0000 +Subject: [PATCH] fix fuse crash problem when rm node + +When using fuse to mount a filesystem, there is a problem that +when running command "rm" to delete a file, fuse will crash. +This patch fixes the problem. + +Signed-off-by: Shijie Luo +--- + libfuse-fuse-2.9.7/lib/fuse.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/libfuse-fuse-2.9.7/lib/fuse.c b/libfuse-fuse-2.9.7/lib/fuse.c +index 0913388..f9b6b07 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse.c ++++ b/libfuse-fuse-2.9.7/lib/fuse.c +@@ -720,10 +720,9 @@ static void unhash_name(struct fuse *f, struct node *node) + *nodep = node->name_next; + node->name_next = NULL; + unref_node(f, node->parent); +- if (node->name != node->inline_name) { ++ if (node->name != node->inline_name) + free(node->name); +- node->name = NULL; +- } ++ node->name = NULL; + node->parent = NULL; + f->name_table.use--; + +-- +1.8.3.1 + diff --git a/fuse-0001-More-parentheses.patch b/fuse-0001-More-parentheses.patch new file mode 100644 index 0000000..4d34710 --- /dev/null +++ b/fuse-0001-More-parentheses.patch @@ -0,0 +1,52 @@ +From 22ba14e45e84e0bd12a9ab1c9d0460b9ae27c10c Mon Sep 17 00:00:00 2001 +From: Peter Lemenkov +Date: Mon, 9 Aug 2010 12:10:40 +0400 +Subject: [PATCH 1/1] More parentheses + +Signed-off-by: Peter Lemenkov +--- + lib/fuse.c | 8 +++----- + lib/fuse_lowlevel.c | 2 +- + 2 files changed, 4 insertions(+), 6 deletions(-) + +diff --git a/lib/fuse.c b/lib/fuse.c +index d511964..328ebba 100644 +--- a/lib/fuse.c ++++ b/lib/fuse.c +@@ -991,17 +991,15 @@ static int fuse_compat_open(struct fuse_fs *fs, const char *path, + { + int err; + if (!fs->compat || fs->compat >= 25) +- err = fs->op.open(path, fi); ++ err = (fs->op.open)(path, fi); + else if (fs->compat == 22) { + struct fuse_file_info_compat tmp; + memcpy(&tmp, fi, sizeof(tmp)); +- err = ((struct fuse_operations_compat22 *) &fs->op)->open(path, +- &tmp); ++ err = (((struct fuse_operations_compat22 *) &fs->op)->open)(path, &tmp); + memcpy(fi, &tmp, sizeof(tmp)); + fi->fh = tmp.fh; + } else +- err = ((struct fuse_operations_compat2 *) &fs->op) +- ->open(path, fi->flags); ++ err = (((struct fuse_operations_compat2 *) &fs->op)->open)(path, fi->flags); + return err; + } + +diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c +index c86a910..4f19d61 100644 +--- a/lib/fuse_lowlevel.c ++++ b/lib/fuse_lowlevel.c +@@ -716,7 +716,7 @@ static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) + fi.flags = arg->flags; + + if (req->f->op.open) +- req->f->op.open(req, nodeid, &fi); ++ (req->f->op.open)(req, nodeid, &fi); + else + fuse_reply_open(req, &fi); + } +-- +1.7.9.3 + diff --git a/fuse-2.9.2-namespace-conflict-fix.patch b/fuse-2.9.2-namespace-conflict-fix.patch new file mode 100644 index 0000000..ae67e7d --- /dev/null +++ b/fuse-2.9.2-namespace-conflict-fix.patch @@ -0,0 +1,21 @@ +diff -up fuse-2.9.2/include/fuse_kernel.h.conflictfix fuse-2.9.2/include/fuse_kernel.h +--- fuse-2.9.2/include/fuse_kernel.h.conflictfix 2013-06-26 09:31:57.862198038 -0400 ++++ fuse-2.9.2/include/fuse_kernel.h 2013-06-26 09:32:19.679198365 -0400 +@@ -88,12 +88,16 @@ + #ifndef _LINUX_FUSE_H + #define _LINUX_FUSE_H + +-#include ++#ifdef __linux__ ++#include ++#else ++#include + #define __u64 uint64_t + #define __s64 int64_t + #define __u32 uint32_t + #define __s32 int32_t + #define __u16 uint16_t ++#endif + + /* + * Version negotiation: diff --git a/fuse-2.9.7.tar.gz b/fuse-2.9.7.tar.gz new file mode 100644 index 0000000..390824e Binary files /dev/null and b/fuse-2.9.7.tar.gz differ diff --git a/fuse-3.0.0-More-parentheses.patch b/fuse-3.0.0-More-parentheses.patch new file mode 100644 index 0000000..6d10168 --- /dev/null +++ b/fuse-3.0.0-More-parentheses.patch @@ -0,0 +1,13 @@ +diff -up libfuse-fuse-3.0.0/lib/fuse.c.parens libfuse-fuse-3.0.0/lib/fuse.c +--- libfuse-fuse-3.0.0/lib/fuse.c.parens 2017-03-21 09:31:31.979537796 -0400 ++++ libfuse-fuse-3.0.0/lib/fuse.c 2017-03-21 09:31:42.676250718 -0400 +@@ -1653,7 +1653,7 @@ int fuse_fs_open(struct fuse_fs *fs, con + fprintf(stderr, "open flags: 0x%x %s\n", fi->flags, + path); + +- err = fs->op.open(path, fi); ++ err = (fs->op.open)(path, fi); + + if (fs->debug && !err) + fprintf(stderr, " open[%llu] flags: 0x%x %s\n", +diff -up libfuse-fuse-3.0.0/lib/fuse_lowlevel.c.parens libfuse-fuse-3.0.0/lib/fuse_lowlevel.c diff --git a/fuse-3.2.1-no-dev.patch b/fuse-3.2.1-no-dev.patch new file mode 100644 index 0000000..371fc24 --- /dev/null +++ b/fuse-3.2.1-no-dev.patch @@ -0,0 +1,19 @@ +diff -up libfuse-fuse-3.2.1/util/install_helper.sh.nodev libfuse-fuse-3.2.1/util/install_helper.sh +--- libfuse-fuse-3.2.1/util/install_helper.sh.nodev 2017-11-14 15:48:15.000000000 -0500 ++++ libfuse-fuse-3.2.1/util/install_helper.sh 2017-11-16 15:23:20.552413938 -0500 +@@ -11,14 +11,9 @@ bindir="$2" + udevrulesdir="$3" + prefix="${MESON_INSTALL_DESTDIR_PREFIX}" + +-chown root:root "${prefix}/${bindir}/fusermount3" ++# chown root:root "${prefix}/${bindir}/fusermount3" + chmod u+s "${prefix}/${bindir}/fusermount3" + +-if test ! -e "${DESTDIR}/dev/fuse"; then +- mkdir -p "${DESTDIR}/dev" +- mknod "${DESTDIR}/dev/fuse" -m 0666 c 10 229 +-fi +- + install -D -m 644 "${MESON_SOURCE_ROOT}/util/udev.rules" \ + "${DESTDIR}/${udevrulesdir}/99-fuse3.rules" + diff --git a/fuse-3.2.3.tar.gz b/fuse-3.2.3.tar.gz new file mode 100644 index 0000000..77c4871 Binary files /dev/null and b/fuse-3.2.3.tar.gz differ diff --git a/fuse-exit-when-got-EINVAL-error.patch b/fuse-exit-when-got-EINVAL-error.patch new file mode 100644 index 0000000..3b9ca38 --- /dev/null +++ b/fuse-exit-when-got-EINVAL-error.patch @@ -0,0 +1,29 @@ +From 0aa4f47172f5f9a5001be8cda988b89d4d54874c Mon Sep 17 00:00:00 2001 +From: +Date: Tue, 4 Dec 2018 14:11:31 +0800 +Subject: [PATCH] fuse: exit when got EINVAL error + +Signed-off-by: +--- + lib/fuse_kern_chan.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +index 1096fa3..dc964e1 100644 +--- a/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c ++++ b/libfuse-fuse-2.9.7/lib/fuse_kern_chan.c +@@ -72,6 +72,11 @@ static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[], + + assert(se != NULL); + ++ /* EINVAL means can not reply the request any more */ ++ if (err == EINVAL) { ++ fuse_session_exit(se); ++ return 0; ++ } + /* ENOENT means the operation was interrupted */ + if (!fuse_session_exited(se) && err != ENOENT) + perror("fuse: writing device"); +-- +1.8.3.1 + diff --git a/fuse.conf b/fuse.conf new file mode 100644 index 0000000..cd4c6bd --- /dev/null +++ b/fuse.conf @@ -0,0 +1,2 @@ +# mount_max = 1000 +# user_allow_other diff --git a/fuse.spec b/fuse.spec new file mode 100644 index 0000000..202857e --- /dev/null +++ b/fuse.spec @@ -0,0 +1,268 @@ +%global fuse2ver 2.9.7 +%global fuse3ver 3.2.3 + +Name: fuse +Version: %{fuse2ver} +Release: 22 +Summary: User space File System of fuse2 +License: GPL+ and LGPLv2+ +URL: http://fuse.sf.net +#fuse2 sources +Source0: https://github.com/libfuse/libfuse/archive/%{name}-%{fuse2ver}.tar.gz +#fuse3 sources +Source1: https://github.com/libfuse/libfuse/archive/%{name}-%{fuse3ver}.tar.gz +Source2: %{name}.conf + +Patch1: fuse-3.0.0-More-parentheses.patch +Patch2: fuse-0001-More-parentheses.patch +Patch3: fuse-2.9.2-namespace-conflict-fix.patch +Patch4: fuse-3.2.1-no-dev.patch + +Patch6000: CVE-2018-10906.patch +Patch6001: 0015-libfuse-fix-fs-cleanup.patch +Patch6002: 0032-fuse_opt_parse-fix-memory-leak.patch +Patch6003: 0530-fusermount-refuse-unknown-options.patch +Patch6004: 0531-fusermount-whitelist-known-good-filesystems-for-moun.patch +Patch6005: 0533-fusermount-Fix-memory-leaks.patch +Patch6006: 0545-Fix-invalid-free-of-memory-pointer-in-struct-fuse_bu.patch +Patch6007: 0546-Fix-memory-leak-of-FUSE-modules.patch + +Patch9000: bugfix-increase-idle-thread.patch +Patch9001: bugfix-invalid-free-and-core.patch +Patch9002: bugfix-memory-leak-and-wild-ptr.patch +Patch9003: fuse-exit-when-got-EINVAL-error.patch +Patch9004: fix-fuse-crash-problem-when-rm-node.patch + +BuildRequires: libselinux-devel, pkgconfig, systemd-udev, meson, fdupes +BuildRequires: autoconf, automake, libtool, gettext-devel, ninja-build +Requires: which +Conflicts: filesystem < 3 +Provides: fuse-common +Obsoletes: fuse-common +Provides: %{name}-libs +Obsoletes: %{name}-libs + +%description +FUSE (Filesystem in Userspace) is an interface for userspace programs to export +a filesystem to the Linux kernel. The FUSE project consists of two components: +the fuse kernel module (maintained in the regular kernel repositories) and the +libfuse userspace library (maintained in this repository). libfuse provides the +reference implementation for communicating with the FUSE kernel module. + +%package -n fuse3 +Version: %{fuse3ver} +Summary: User space File System of fuse2 +Obsoletes: fuse-common +Provides: fuse3-libs +Obsoletes: fuse3-libs + +%description -n fuse3 +FUSE (Filesystem in Userspace) is an interface for userspace programs to export +a filesystem to the Linux kernel. The FUSE project consists of two components: +the fuse kernel module (maintained in the regular kernel repositories) and the +libfuse userspace library (maintained in this repository). libfuse provides the +reference implementation for communicating with the FUSE kernel module. + +%package devel +Version: %{fuse2ver} +Summary: User space File System of fuse2 devel files +Obsoletes: %{name}-libs +Requires: pkgconfig +License: LGPLv2+ +Conflicts: filesystem < 3 + +%description devel +This package contains all include files, libraries and configuration +files needed to develop programs that use the fuse2. + +%package -n fuse3-devel +Version: %{fuse3ver} +Summary: User space File System of fuse3 devel files +Obsoletes: %{name}3-libs +Requires: pkgconfig +License: LGPLv2+ +Conflicts: filesystem < 3 + +%description -n fuse3-devel +This package contains all include files, libraries and configuration +files needed to develop programs that use the fuse3. + +%package help +Summary: Including man files for fuse +Requires: man + +%description help +This contains man files for the using of fuse + +%prep +%setup -q -T -c -n fuse2and3 -a0 -a1 + +# fuse 2 +pushd lib%{name}-%{name}-%{fuse2ver} +./makeconf.sh +%patch2 -p1 +%patch3 -p1 +popd + +# fuse 3 +pushd lib%{name}-%{name}-%{fuse3ver} +%patch1 -p1 +%patch4 -p1 +%patch6003 -p1 +%patch6005 -p1 +%patch6006 -p1 +%patch6007 -p1 +popd + +%patch9000 -p1 +%patch9001 -p1 +%patch9002 -p1 +%patch9003 -p1 +%patch6000 -p1 +%patch9004 -p1 +%patch6001 -p1 +%patch6002 -p1 +%patch6004 -p1 + +%build +# fuse 2 +pushd lib%{name}-%{name}-%{fuse2ver} +export MOUNT_FUSE_PATH="%{_sbindir}" +export CFLAGS="%{optflags} -D_GNU_SOURCE" +%configure --enable-lib +%make_build +popd + +# fuse 3 +pushd lib%{name}-%{name}-%{fuse3ver} +%meson +%meson_build +popd + +%install +# fuse 2 +pushd lib%{name}-%{name}-%{fuse2ver} +%make_install +popd + +# fuse 3 +pushd lib%{name}-%{name}-%{fuse3ver} +export MESON_INSTALL_DESTDIR_PREFIX=%{buildroot}/usr +%meson_install +popd + +chmod 0755 %{buildroot}/%{_bindir}/fusermount3 + +rm -f %{buildroot}/%{_libdir}/*.a +rm -f %{buildroot}%{_sysconfdir}/init.d/fuse +rm -f %{buildroot}%{_sysconfdir}/init.d/fuse3 +rm -f %{buildroot}%{_sysconfdir}/udev/rules.d/99-fuse.rules +rm -f %{buildroot}/usr/lib/udev/rules.d/99-fuse3.rules +find %{buildroot} -type f -name "*.la" -delete -print + +# Install config-file +install -p -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir} + + +%post -n fuse -p /sbin/ldconfig +%post -n fuse3 -p /sbin/ldconfig +%postun -n fuse -p /sbin/ldconfig +%postun -n fuse3 -p /sbin/ldconfig + +%files +%doc libfuse-fuse-%{fuse2ver}/{AUTHORS,ChangeLog,NEWS,README*} +%license libfuse-fuse-%{fuse2ver}/COPYING +%{_sbindir}/mount.fuse +%attr(4755,root,root) %{_bindir}/fusermount +%{_bindir}/ulockmgr_server +%{_libdir}/libfuse.so.* +%{_libdir}/libulockmgr.so.* +%config(noreplace) %{_sysconfdir}/%{name}.conf + +%files -n fuse3 +%doc libfuse-fuse-%{fuse3ver}/{AUTHORS,ChangeLog*,README*} +%license libfuse-fuse-%{fuse3ver}/COPYING +%{_sbindir}/mount.fuse3 +%attr(4755,root,root) %{_bindir}/fusermount3 +%{_libdir}/libfuse3.so.* +%config(noreplace) %{_sysconfdir}/%{name}.conf + +%files devel +%{_includedir}/fuse.h +%{_includedir}/ulockmgr.h +%{_includedir}/fuse +%{_libdir}/libfuse.so +%{_libdir}/libulockmgr.so +%{_libdir}/pkgconfig/fuse.pc + +%files -n fuse3-devel +%{_includedir}/fuse3/ +%{_libdir}/libfuse3.so +%{_libdir}/pkgconfig/fuse3.pc + +%files help +%{_mandir}/man1/* +%{_mandir}/man8/* + + +%changelog +* Wed Sep 4 2019 zoujing - 2.9.7-22 +- Type:enhancemnet +- ID:NA +- SUG:restart +- DESCi:openEuler Debranding + +* Fri Aug 23 2019 zoujing - 2.9.7-21 +- Type:enhancement +- ID:NA +- SUG:restart +- DESC: remove sensitive information + +* Thu Aug 22 2019 zoujing - 2.9.7-20 +- Type: enhancement +- ID:NA +- SUG:restart +- DESC:rename patch name + +* Mon Aug 12 2019 huangzheng - 2.9.7-19 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:safety code review, delete sensitive information + +* Tue Jul 23 2019 Shijie Luo - 2.9.7-18 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix fuse crash problem when rm node + +* Fri Apr 19 2019 wangchan - 2.9.7-17 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: bfuse-fix-fs-cleanup + fuse_opt_parse(): fix memory leak + fusermount: refuse unknown options + fusermount: whitelist known-good filesystems for mountpoints + fusermount: Fix memory leaks + Fix invalid free of memory pointer in 'struct fuse_buf' + Fix memory leak of FUSE modules + +* Fri Mar 22 2019 yangjian - 2.9.7-16 +- Type:cves +- ID:CVE-2018-10906 +- SUG:NA +- DESC:fix CVE-2018-10906 + +* Fri Jan 25 2019 liuqianya - 2.9.7-15 +- Type:bugfix +- ID:NA +- SUG:NA + DESC:increase idle thread + invalid free and core + memory leak and wild ptr + fuse exit when got EINVAL error + +* Wed Jul 18 2018 openEuler Buildteam - 2.9.7-14 +- Package init +