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