All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com>
To: qemu-devel@nongnu.org, renzhen@linux.alibaba.com,
	eguan@linux.alibaba.com, ganesh.mahalingam@intel.com,
	m.mizuma@jp.fujitsu.com, mszeredi@redhat.com,
	misono.tomohiro@jp.fujitsu.com, tao.peng@linux.alibaba.com,
	piaojun@huawei.com, stefanha@redhat.com, vgoyal@redhat.com,
	mst@redhat.com, berrange@redhat.com
Subject: [PATCH 12/25] virtiofsd: check input buffer size in fuse_lowlevel.c ops
Date: Thu, 24 Oct 2019 12:27:05 +0100	[thread overview]
Message-ID: <20191024112718.34657-13-dgilbert@redhat.com> (raw)
In-Reply-To: <20191024112718.34657-1-dgilbert@redhat.com>

From: Stefan Hajnoczi <stefanha@redhat.com>

Each FUSE operation involves parsing the input buffer.  Currently the
code assumes the input buffer is large enough for the expected
arguments.  This patch uses fuse_mbuf_iter to check the size.

Most operations are simple to convert.  Some are more complicated due to
variable-length inputs or different sizes depending on the protocol
version.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 contrib/virtiofsd/fuse_lowlevel.c | 621 +++++++++++++++++++++++-------
 1 file changed, 482 insertions(+), 139 deletions(-)

diff --git a/contrib/virtiofsd/fuse_lowlevel.c b/contrib/virtiofsd/fuse_lowlevel.c
index 7927348398..d032e411e1 100644
--- a/contrib/virtiofsd/fuse_lowlevel.c
+++ b/contrib/virtiofsd/fuse_lowlevel.c
@@ -15,6 +15,7 @@
 #include "fuse_misc.h"
 #include "fuse_virtio.h"
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
@@ -27,7 +28,6 @@
 
 
 
-#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
 #define OFFSET_MAX 0x7fffffffffffffffLL
 
 struct fuse_pollhandle {
@@ -705,9 +705,14 @@ int fuse_reply_poll(fuse_req_t req, unsigned revents)
 	return send_reply_ok(req, &arg, sizeof(arg));
 }
 
-static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_lookup(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
-	char *name = (char *) inarg;
+	const char *name = fuse_mbuf_iter_advance_str(iter);
+	if (!name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.lookup)
 		req->se->op.lookup(req, nodeid, name);
@@ -715,9 +720,16 @@ static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_forget(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
-	struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg;
+	struct fuse_forget_in *arg;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.forget)
 		req->se->op.forget(req, nodeid, arg->nlookup);
@@ -726,20 +738,47 @@ static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 }
 
 static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid,
-			    const void *inarg)
+			    struct fuse_mbuf_iter *iter)
 {
-	struct fuse_batch_forget_in *arg = (void *) inarg;
-	struct fuse_forget_one *param = (void *) PARAM(arg);
-	unsigned int i;
+	struct fuse_batch_forget_in *arg;
+	struct fuse_forget_data *forgets;
+	size_t scount;
 
 	(void) nodeid;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_none(req);
+	}
+
+	/* Prevent integer overflow.  The compiler emits the following warning
+	 * unless we use the scount local variable:
+	 *
+	 * error: comparison is always false due to limited range of data type
+	 * [-Werror=type-limits]
+	 *
+	 * This may be true on 64-bit hosts but we need this check for 32-bit
+	 * hosts.
+	 */
+	scount = arg->count;
+	if (scount > SIZE_MAX / sizeof(forgets[0])) {
+		fuse_reply_none(req);
+		return;
+	}
+
+	forgets = fuse_mbuf_iter_advance(iter, arg->count *
+					 sizeof(forgets[0]));
+	if (!forgets) {
+		fuse_reply_none(req);
+		return;
+	}
+
 	if (req->se->op.forget_multi) {
-		req->se->op.forget_multi(req, arg->count,
-				     (struct fuse_forget_data *) param);
+		req->se->op.forget_multi(req, arg->count, forgets);
 	} else if (req->se->op.forget) {
+		unsigned int i;
+
 		for (i = 0; i < arg->count; i++) {
-			struct fuse_forget_one *forget = &param[i];
 			struct fuse_req *dummy_req;
 
 			dummy_req = fuse_ll_alloc_req(req->se);
@@ -750,8 +789,8 @@ static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid,
 			dummy_req->ctx = req->ctx;
 			dummy_req->ch = NULL;
 
-			req->se->op.forget(dummy_req, forget->nodeid,
-					  forget->nlookup);
+			req->se->op.forget(dummy_req, forgets[i].ino,
+					   forgets[i].nlookup);
 		}
 		fuse_reply_none(req);
 	} else {
@@ -759,13 +798,20 @@ static void do_batch_forget(fuse_req_t req, fuse_ino_t nodeid,
 	}
 }
 
-static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_getattr(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
 	struct fuse_file_info *fip = NULL;
 	struct fuse_file_info fi;
 
 	if (req->se->conn.proto_minor >= 9) {
-		struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg;
+		struct fuse_getattr_in *arg;
+
+		arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+		if (!arg) {
+			fuse_reply_err(req, EINVAL);
+			return;
+		}
 
 		if (arg->getattr_flags & FUSE_GETATTR_FH) {
 			memset(&fi, 0, sizeof(fi));
@@ -780,14 +826,21 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_setattr(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
-	struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg;
-
 	if (req->se->op.setattr) {
+		struct fuse_setattr_in *arg;
 		struct fuse_file_info *fi = NULL;
 		struct fuse_file_info fi_store;
 		struct stat stbuf;
+
+		arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+		if (!arg) {
+			fuse_reply_err(req, EINVAL);
+			return;
+		}
+
 		memset(&stbuf, 0, sizeof(stbuf));
 		convert_attr(arg, &stbuf);
 		if (arg->valid & FATTR_FH) {
@@ -812,9 +865,16 @@ static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_access(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
-	struct fuse_access_in *arg = (struct fuse_access_in *) inarg;
+	struct fuse_access_in *arg;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.access)
 		req->se->op.access(req, nodeid, arg->mask);
@@ -822,9 +882,10 @@ static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_readlink(fuse_req_t req, fuse_ino_t nodeid,
+			struct fuse_mbuf_iter *iter)
 {
-	(void) inarg;
+	(void) iter;
 
 	if (req->se->op.readlink)
 		req->se->op.readlink(req, nodeid);
@@ -832,15 +893,24 @@ static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg;
-	char *name = PARAM(arg);
+	bool compat = req->se->conn.proto_minor < 12;
+	struct fuse_mknod_in *arg;
+	const char *name;
 
-	if (req->se->conn.proto_minor >= 12)
+	arg = fuse_mbuf_iter_advance(iter,
+			compat ? FUSE_COMPAT_MKNOD_IN_SIZE : sizeof(*arg));
+	name = fuse_mbuf_iter_advance_str(iter);
+	if (!arg || !name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
+	if (!compat) {
 		req->ctx.umask = arg->umask;
-	else
-		name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE;
+	}
 
 	if (req->se->op.mknod)
 		req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
@@ -848,22 +918,40 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg;
+	bool compat = req->se->conn.proto_minor < 12;
+	struct fuse_mkdir_in *arg;
+	const char *name;
 
-	if (req->se->conn.proto_minor >= 12)
+	arg = fuse_mbuf_iter_advance(iter,
+			compat ? sizeof(uint32_t) : sizeof(*arg));
+	name = fuse_mbuf_iter_advance_str(iter);
+	if (!arg || !name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
+	if (!compat) {
 		req->ctx.umask = arg->umask;
+	}
 
 	if (req->se->op.mkdir)
-		req->se->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
+		req->se->op.mkdir(req, nodeid, name, arg->mode);
 	else
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_unlink(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
-	char *name = (char *) inarg;
+	const char *name = fuse_mbuf_iter_advance_str(iter);
+
+	if (!name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.unlink)
 		req->se->op.unlink(req, nodeid, name);
@@ -871,9 +959,15 @@ static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	char *name = (char *) inarg;
+	const char *name = fuse_mbuf_iter_advance_str(iter);
+
+	if (!name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.rmdir)
 		req->se->op.rmdir(req, nodeid, name);
@@ -881,10 +975,16 @@ static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_symlink(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
-	char *name = (char *) inarg;
-	char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1;
+	const char *name = fuse_mbuf_iter_advance_str(iter);
+	const char *linkname = fuse_mbuf_iter_advance_str(iter);
+
+	if (!name || !linkname) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.symlink)
 		req->se->op.symlink(req, linkname, nodeid, name);
@@ -892,11 +992,20 @@ static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_rename(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
-	struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg;
-	char *oldname = PARAM(arg);
-	char *newname = oldname + strlen(oldname) + 1;
+	struct fuse_rename_in *arg;
+	const char *oldname;
+	const char *newname;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	oldname = fuse_mbuf_iter_advance_str(iter);
+	newname = fuse_mbuf_iter_advance_str(iter);
+	if (!arg || !oldname || !newname) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.rename)
 		req->se->op.rename(req, nodeid, oldname, arg->newdir, newname,
@@ -905,11 +1014,20 @@ static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_rename2(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
-	struct fuse_rename2_in *arg = (struct fuse_rename2_in *) inarg;
-	char *oldname = PARAM(arg);
-	char *newname = oldname + strlen(oldname) + 1;
+	struct fuse_rename2_in *arg;
+	const char *oldname;
+	const char *newname;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	oldname = fuse_mbuf_iter_advance_str(iter);
+	newname = fuse_mbuf_iter_advance_str(iter);
+	if (!arg || !oldname || !newname) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.rename)
 		req->se->op.rename(req, nodeid, oldname, arg->newdir, newname,
@@ -918,42 +1036,65 @@ static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_link(fuse_req_t req, fuse_ino_t nodeid,
+		    struct fuse_mbuf_iter *iter)
 {
-	struct fuse_link_in *arg = (struct fuse_link_in *) inarg;
+	struct fuse_link_in *arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	const char *name = fuse_mbuf_iter_advance_str(iter);
+
+	if (!arg || !name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.link)
-		req->se->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
+		req->se->op.link(req, arg->oldnodeid, nodeid, name);
 	else
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_create(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
-	struct fuse_create_in *arg = (struct fuse_create_in *) inarg;
-
 	if (req->se->op.create) {
+		bool compat = req->se->conn.proto_minor < 12;
+		struct fuse_create_in *arg;
 		struct fuse_file_info fi;
-		char *name = PARAM(arg);
+		const char *name;
+
+		arg = fuse_mbuf_iter_advance(iter, compat ?
+				sizeof(struct fuse_open_in) :
+				sizeof(*arg));
+		name = fuse_mbuf_iter_advance_str(iter);
+		if (!arg || !name) {
+			fuse_reply_err(req, EINVAL);
+			return;
+		}
 
 		memset(&fi, 0, sizeof(fi));
 		fi.flags = arg->flags;
 
-		if (req->se->conn.proto_minor >= 12)
+		if (!compat) {
 			req->ctx.umask = arg->umask;
-		else
-			name = (char *) inarg + sizeof(struct fuse_open_in);
+		}
 
 		req->se->op.create(req, nodeid, name, arg->mode, &fi);
 	} else
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_open(fuse_req_t req, fuse_ino_t nodeid,
+		    struct fuse_mbuf_iter *iter)
 {
-	struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
+	struct fuse_open_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.flags = arg->flags;
 
@@ -963,16 +1104,21 @@ static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_open(req, &fi);
 }
 
-static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_read(fuse_req_t req, fuse_ino_t nodeid,
+		    struct fuse_mbuf_iter *iter)
 {
-	struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
-
 	if (req->se->op.read) {
+		bool compat = req->se->conn.proto_minor < 9;
+		struct fuse_read_in *arg;
 		struct fuse_file_info fi;
 
+		arg = fuse_mbuf_iter_advance(iter, compat ?
+				offsetof(struct fuse_read_in, lock_owner) :
+				sizeof(*arg));
+
 		memset(&fi, 0, sizeof(fi));
 		fi.fh = arg->fh;
-		if (req->se->conn.proto_minor >= 9) {
+		if (!compat) {
 			fi.lock_owner = arg->lock_owner;
 			fi.flags = arg->flags;
 		}
@@ -981,22 +1127,34 @@ static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_write(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	struct fuse_write_in *arg = (struct fuse_write_in *) inarg;
+	bool compat = req->se->conn.proto_minor < 9;
+	struct fuse_write_in *arg;
 	struct fuse_file_info fi;
-	char *param;
+	const char *param;
+
+	arg = fuse_mbuf_iter_advance(iter, compat ?
+			FUSE_COMPAT_WRITE_IN_SIZE : sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
+	param = fuse_mbuf_iter_advance(iter, arg->size);
+	if (!param) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 	fi.writepage = (arg->write_flags & FUSE_WRITE_CACHE) != 0;
 
-	if (req->se->conn.proto_minor < 9) {
-		param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
-	} else {
+	if (!compat) {
 		fi.lock_owner = arg->lock_owner;
 		fi.flags = arg->flags;
-		param = PARAM(arg);
 	}
 
 	if (req->se->op.write)
@@ -1062,16 +1220,27 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid,
 	se->op.write_buf(req, nodeid, pbufv, arg->offset, &fi);
 }
 
-static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_flush(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg;
+	bool compat = req->se->conn.proto_minor < 7;
+	struct fuse_flush_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, compat ?
+			offsetof(struct fuse_flush_in, lock_owner) :
+			sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 	fi.flush = 1;
-	if (req->se->conn.proto_minor >= 7)
+	if (!compat) {
 		fi.lock_owner = arg->lock_owner;
+	}
 
 	if (req->se->op.flush)
 		req->se->op.flush(req, nodeid, &fi);
@@ -1079,21 +1248,31 @@ static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_release(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
-	struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
+	bool compat = req->se->conn.proto_minor < 8;
+	struct fuse_release_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, compat ?
+			offsetof(struct fuse_release_in, lock_owner) :
+			sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.flags = arg->flags;
 	fi.fh = arg->fh;
-	if (req->se->conn.proto_minor >= 8) {
+	if (!compat) {
 		fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
 		fi.lock_owner = arg->lock_owner;
-	}
-	if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) {
-		fi.flock_release = 1;
-		fi.lock_owner = arg->lock_owner;
+
+		if (arg->release_flags & FUSE_RELEASE_FLOCK_UNLOCK) {
+			fi.flock_release = 1;
+		}
 	}
 
 	if (req->se->op.release)
@@ -1102,11 +1281,19 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, 0);
 }
 
-static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_fsync(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
+	struct fuse_fsync_in *arg;
 	struct fuse_file_info fi;
-	int datasync = arg->fsync_flags & 1;
+	int datasync;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+	datasync = arg->fsync_flags & 1;
 
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
@@ -1120,11 +1307,18 @@ static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_opendir(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
-	struct fuse_open_in *arg = (struct fuse_open_in *) inarg;
+	struct fuse_open_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.flags = arg->flags;
 
@@ -1134,11 +1328,18 @@ static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_open(req, &fi);
 }
 
-static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_readdir(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
-	struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
+	struct fuse_read_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 
@@ -1148,11 +1349,18 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid,
+			   struct fuse_mbuf_iter *iter)
 {
-	struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
+	struct fuse_read_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 
@@ -1162,11 +1370,18 @@ static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid,
+			  struct fuse_mbuf_iter *iter)
 {
-	struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
+	struct fuse_release_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.flags = arg->flags;
 	fi.fh = arg->fh;
@@ -1177,11 +1392,19 @@ static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, 0);
 }
 
-static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid,
+			struct fuse_mbuf_iter *iter)
 {
-	struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg;
+	struct fuse_fsync_in *arg;
 	struct fuse_file_info fi;
-	int datasync = arg->fsync_flags & 1;
+	int datasync;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+	datasync = arg->fsync_flags & 1;
 
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
@@ -1192,10 +1415,11 @@ static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_statfs(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
 	(void) nodeid;
-	(void) inarg;
+	(void) iter;
 
 	if (req->se->op.statfs)
 		req->se->op.statfs(req, nodeid);
@@ -1208,11 +1432,25 @@ static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 	}
 }
 
-static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid,
+			struct fuse_mbuf_iter *iter)
 {
-	struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg;
-	char *name = PARAM(arg);
-	char *value = name + strlen(name) + 1;
+	struct fuse_setxattr_in *arg;
+	const char *name;
+	const char *value;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	name = fuse_mbuf_iter_advance_str(iter);
+	if (!arg || !name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
+	value = fuse_mbuf_iter_advance(iter, arg->size);
+	if (!value) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.setxattr)
 		req->se->op.setxattr(req, nodeid, name, value, arg->size,
@@ -1221,19 +1459,35 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid,
+			struct fuse_mbuf_iter *iter)
 {
-	struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
+	struct fuse_getxattr_in *arg;
+	const char *name;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	name = fuse_mbuf_iter_advance_str(iter);
+	if (!arg || !name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.getxattr)
-		req->se->op.getxattr(req, nodeid, PARAM(arg), arg->size);
+		req->se->op.getxattr(req, nodeid, name, arg->size);
 	else
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid,
+			 struct fuse_mbuf_iter *iter)
 {
-	struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg;
+	struct fuse_getxattr_in *arg;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.listxattr)
 		req->se->op.listxattr(req, nodeid, arg->size);
@@ -1241,9 +1495,15 @@ static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid,
+			   struct fuse_mbuf_iter *iter)
 {
-	char *name = (char *) inarg;
+	const char *name = fuse_mbuf_iter_advance_str(iter);
+
+	if (!name) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.removexattr)
 		req->se->op.removexattr(req, nodeid, name);
@@ -1265,12 +1525,19 @@ static void convert_fuse_file_lock(struct fuse_file_lock *fl,
 	flock->l_pid = fl->pid;
 }
 
-static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_getlk(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
+	struct fuse_lk_in *arg;
 	struct fuse_file_info fi;
 	struct flock flock;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 	fi.lock_owner = arg->owner;
@@ -1283,12 +1550,18 @@ static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 }
 
 static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
-			    const void *inarg, int sleep)
+			    struct fuse_mbuf_iter *iter, int sleep)
 {
-	struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg;
+	struct fuse_lk_in *arg;
 	struct fuse_file_info fi;
 	struct flock flock;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 	fi.lock_owner = arg->owner;
@@ -1323,14 +1596,16 @@ static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid,
 	}
 }
 
-static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_setlk(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	do_setlk_common(req, nodeid, inarg, 0);
+	do_setlk_common(req, nodeid, iter, 0);
 }
 
-static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid,
+		      struct fuse_mbuf_iter *iter)
 {
-	do_setlk_common(req, nodeid, inarg, 1);
+	do_setlk_common(req, nodeid, iter, 1);
 }
 
 static int find_interrupted(struct fuse_session *se, struct fuse_req *req)
@@ -1372,12 +1647,20 @@ static int find_interrupted(struct fuse_session *se, struct fuse_req *req)
 	return 0;
 }
 
-static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid,
+			 struct fuse_mbuf_iter *iter)
 {
-	struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg;
+	struct fuse_interrupt_in *arg;
 	struct fuse_session *se = req->se;
 
 	(void) nodeid;
+
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	if (se->debug)
 		fuse_log(FUSE_LOG_DEBUG, "INTERRUPT: %llu\n",
 			(unsigned long long) arg->unique);
@@ -1415,9 +1698,15 @@ static struct fuse_req *check_interrupt(struct fuse_session *se,
 		return NULL;
 }
 
-static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_bmap(fuse_req_t req, fuse_ino_t nodeid,
+		    struct fuse_mbuf_iter *iter)
 {
-	struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg;
+	struct fuse_bmap_in *arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
 
 	if (req->se->op.bmap)
 		req->se->op.bmap(req, nodeid, arg->blocksize, arg->block);
@@ -1425,19 +1714,35 @@ static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid,
+		     struct fuse_mbuf_iter *iter)
 {
-	struct fuse_ioctl_in *arg = (struct fuse_ioctl_in *) inarg;
-	unsigned int flags = arg->flags;
-	void *in_buf = arg->in_size ? PARAM(arg) : NULL;
+	struct fuse_ioctl_in *arg;
+	unsigned int flags;
+	void *in_buf = NULL;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
+	flags = arg->flags;
 	if (flags & FUSE_IOCTL_DIR &&
 	    !(req->se->conn.want & FUSE_CAP_IOCTL_DIR)) {
 		fuse_reply_err(req, ENOTTY);
 		return;
 	}
 
+	if (arg->in_size) {
+		in_buf = fuse_mbuf_iter_advance(iter, arg->in_size);
+		if (!in_buf) {
+			fuse_reply_err(req, EINVAL);
+			return;
+		}
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 
@@ -1459,11 +1764,18 @@ void fuse_pollhandle_destroy(struct fuse_pollhandle *ph)
 	free(ph);
 }
 
-static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_poll(fuse_req_t req, fuse_ino_t nodeid,
+		    struct fuse_mbuf_iter *iter)
 {
-	struct fuse_poll_in *arg = (struct fuse_poll_in *) inarg;
+	struct fuse_poll_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 	fi.poll_events = arg->events;
@@ -1487,11 +1799,18 @@ static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 	}
 }
 
-static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid,
+			 struct fuse_mbuf_iter *iter)
 {
-	struct fuse_fallocate_in *arg = (struct fuse_fallocate_in *) inarg;
+	struct fuse_fallocate_in *arg;
 	struct fuse_file_info fi;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi, 0, sizeof(fi));
 	fi.fh = arg->fh;
 
@@ -1501,11 +1820,18 @@ static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in, const void *inarg)
+static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in,
+			       struct fuse_mbuf_iter *iter)
 {
-	struct fuse_copy_file_range_in *arg = (struct fuse_copy_file_range_in *) inarg;
+	struct fuse_copy_file_range_in *arg;
 	struct fuse_file_info fi_in, fi_out;
 
+	arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
 	memset(&fi_in, 0, sizeof(fi_in));
 	fi_in.fh = arg->fh_in;
 
@@ -1522,15 +1848,34 @@ static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in, const void
 		fuse_reply_err(req, ENOSYS);
 }
 
-static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_init(fuse_req_t req, fuse_ino_t nodeid,
+		    struct fuse_mbuf_iter *iter)
 {
-	struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
+	size_t compat_size = offsetof(struct fuse_init_in, max_readahead);
+	struct fuse_init_in *arg;
 	struct fuse_init_out outarg;
 	struct fuse_session *se = req->se;
 	size_t bufsize = se->bufsize;
 	size_t outargsize = sizeof(outarg);
 
 	(void) nodeid;
+
+	/* First consume the old fields... */
+	arg = fuse_mbuf_iter_advance(iter, compat_size);
+	if (!arg) {
+		fuse_reply_err(req, EINVAL);
+		return;
+	}
+
+	/* ...and now consume the new fields. */
+	if (arg->major == 7 && arg->minor >= 6) {
+		if (!fuse_mbuf_iter_advance(iter, sizeof(*arg) -
+					    compat_size)) {
+			fuse_reply_err(req, EINVAL);
+			return;
+		}
+	}
+
 	if (se->debug) {
 		fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor);
 		if (arg->major == 7 && arg->minor >= 6) {
@@ -1744,12 +2089,13 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 	send_reply_ok(req, &outarg, outargsize);
 }
 
-static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_destroy(fuse_req_t req, fuse_ino_t nodeid,
+		       struct fuse_mbuf_iter *iter)
 {
 	struct fuse_session *se = req->se;
 
 	(void) nodeid;
-	(void) inarg;
+	(void) iter;
 
 	se->got_destroy = 1;
 	if (se->op.destroy)
@@ -1934,7 +2280,7 @@ int fuse_req_interrupted(fuse_req_t req)
 }
 
 static struct {
-	void (*func)(fuse_req_t, fuse_ino_t, const void *);
+	void (*func)(fuse_req_t, fuse_ino_t, struct fuse_mbuf_iter *);
 	const char *name;
 } fuse_ll_ops[] = {
 	[FUSE_LOOKUP]	   = { do_lookup,      "LOOKUP"	     },
@@ -2013,7 +2359,6 @@ void fuse_session_process_buf_int(struct fuse_session *se,
 	const struct fuse_buf *buf = bufv->buf;
 	struct fuse_mbuf_iter iter = FUSE_MBUF_ITER_INIT(buf);
 	struct fuse_in_header *in;
-	const void *inarg;
 	struct fuse_req *req;
 	int err;
 
@@ -2086,12 +2431,10 @@ void fuse_session_process_buf_int(struct fuse_session *se,
 			fuse_reply_err(intr, EAGAIN);
 	}
 
-	inarg = (void *) &in[1];
 	if (in->opcode == FUSE_WRITE && se->op.write_buf)
 		do_write_buf(req, in->nodeid, &iter, bufv);
 	else
-		fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
-
+		fuse_ll_ops[in->opcode].func(req, in->nodeid, &iter);
 	return;
 
 reply_err:
-- 
2.23.0



  parent reply	other threads:[~2019-10-24 11:55 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-24 11:26 [PATCH 00/25] virtiofs daemon (security) Dr. David Alan Gilbert (git)
2019-10-24 11:26 ` [PATCH 01/25] virtiofsd: passthrough_ll: create new files in caller's context Dr. David Alan Gilbert (git)
2019-10-24 11:26 ` [PATCH 02/25] virtiofsd: passthrough_ll: add lo_map for ino/fh indirection Dr. David Alan Gilbert (git)
2019-10-24 11:26 ` [PATCH 03/25] virtiofsd: passthrough_ll: add ino_map to hide lo_inode pointers Dr. David Alan Gilbert (git)
2019-10-24 11:26 ` [PATCH 04/25] virtiofsd: passthrough_ll: add dirp_map to hide lo_dirp pointers Dr. David Alan Gilbert (git)
2019-10-24 11:26 ` [PATCH 05/25] virtiofsd: passthrough_ll: add fd_map to hide file descriptors Dr. David Alan Gilbert (git)
2019-10-24 11:26 ` [PATCH 06/25] virtiofsd: passthrough_ll: add fallback for racy ops Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 07/25] virtiofsd: validate path components Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 08/25] virtiofsd: Plumb fuse_bufvec through to do_write_buf Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 09/25] virtiofsd: Pass write iov's all the way through Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 10/25] virtiofsd: add fuse_mbuf_iter API Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 11/25] virtiofsd: validate input buffer sizes in do_write_buf() Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` Dr. David Alan Gilbert (git) [this message]
2019-10-24 11:27 ` [PATCH 13/25] virtiofsd: prevent ".." escape in lo_do_lookup() Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 14/25] virtiofsd: prevent ".." escape in lo_do_readdir() Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 15/25] virtiofsd: use /proc/self/fd/ O_PATH file descriptor Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 16/25] virtiofsd: sandbox mount namespace Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 17/25] virtiofsd: move to an empty network namespace Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 18/25] virtiofsd: move to a new pid namespace Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 19/25] virtiofsd: add seccomp whitelist Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 20/25] virtiofsd: Parse flag FUSE_WRITE_KILL_PRIV Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 21/25] virtiofsd: Drop CAP_FSETID if client asked for it Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 22/25] virtiofsd: set maximum RLIMIT_NOFILE limit Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 23/25] virtiofsd: add security guide document Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 24/25] virtiofsd: add --syslog command-line option Dr. David Alan Gilbert (git)
2019-10-24 11:27 ` [PATCH 25/25] virtiofsd: print log only when priority is high enough Dr. David Alan Gilbert (git)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191024112718.34657-13-dgilbert@redhat.com \
    --to=dgilbert@redhat.com \
    --cc=berrange@redhat.com \
    --cc=eguan@linux.alibaba.com \
    --cc=ganesh.mahalingam@intel.com \
    --cc=m.mizuma@jp.fujitsu.com \
    --cc=misono.tomohiro@jp.fujitsu.com \
    --cc=mst@redhat.com \
    --cc=mszeredi@redhat.com \
    --cc=piaojun@huawei.com \
    --cc=qemu-devel@nongnu.org \
    --cc=renzhen@linux.alibaba.com \
    --cc=stefanha@redhat.com \
    --cc=tao.peng@linux.alibaba.com \
    --cc=vgoyal@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.