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