531 lines
13 KiB
Diff
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
|
|
|