132 lines
3.9 KiB
Diff
132 lines
3.9 KiB
Diff
|
|
From fd0cfd7fa7d37a8401c8544dfaac0172d1d35056 Mon Sep 17 00:00:00 2001
|
||
|
|
From: <mashimiao@huawei.com>
|
||
|
|
Date: Fri, 23 Nov 2018 17:14:22 +0800
|
||
|
|
Subject: [PATCH] fuse: fix invalid free and core bug
|
||
|
|
|
||
|
|
Signed-off-by: <mashimiao@huawei.com>
|
||
|
|
---
|
||
|
|
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
|
||
|
|
|