fuse/bugfix-memory-leak-and-wild-ptr.patch
2019-09-30 10:39:10 -04:00

531 lines
13 KiB
Diff

From 276380d842ea9f57f181fc8f37d268d619a753eb Mon Sep 17 00:00:00 2001
From: <mashimiao@huawei.com>
Date: Sat, 1 Dec 2018 11:35:08 +0800
Subject: [PATCH] fix memory leak and wild ptr
Signed-off-by: <mashimiao@huawei.com>
---
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