qemu-kvm/kvm-virtiofsd-check-input-buffer-size-in-fuse_lowlevel.c.patch
Miroslav Rezanina a5bd08701a * Fri Jan 31 2020 Miroslav Rezanina <mrezanin@redhat.com> - 4.2.0-8.el8
- kvm-target-arm-arch_dump-Add-SVE-notes.patch [bz#1725084]
- kvm-vhost-Add-names-to-section-rounded-warning.patch [bz#1779041]
- kvm-vhost-Only-align-sections-for-vhost-user.patch [bz#1779041]
- kvm-vhost-coding-style-fix.patch [bz#1779041]
- kvm-virtio-fs-fix-MSI-X-nvectors-calculation.patch [bz#1694164]
- kvm-vhost-user-fs-remove-vhostfd-property.patch [bz#1694164]
- kvm-build-rename-CONFIG_LIBCAP-to-CONFIG_LIBCAP_NG.patch [bz#1694164]
- kvm-virtiofsd-Pull-in-upstream-headers.patch [bz#1694164]
- kvm-virtiofsd-Pull-in-kernel-s-fuse.h.patch [bz#1694164]
- kvm-virtiofsd-Add-auxiliary-.c-s.patch [bz#1694164]
- kvm-virtiofsd-Add-fuse_lowlevel.c.patch [bz#1694164]
- kvm-virtiofsd-Add-passthrough_ll.patch [bz#1694164]
- kvm-virtiofsd-Trim-down-imported-files.patch [bz#1694164]
- kvm-virtiofsd-Format-imported-files-to-qemu-style.patch [bz#1694164]
- kvm-virtiofsd-remove-mountpoint-dummy-argument.patch [bz#1694164]
- kvm-virtiofsd-remove-unused-notify-reply-support.patch [bz#1694164]
- kvm-virtiofsd-Remove-unused-enum-fuse_buf_copy_flags.patch [bz#1694164]
- kvm-virtiofsd-Fix-fuse_daemonize-ignored-return-values.patch [bz#1694164]
- kvm-virtiofsd-Fix-common-header-and-define-for-QEMU-buil.patch [bz#1694164]
- kvm-virtiofsd-Trim-out-compatibility-code.patch [bz#1694164]
- kvm-vitriofsd-passthrough_ll-fix-fallocate-ifdefs.patch [bz#1694164]
- kvm-virtiofsd-Make-fsync-work-even-if-only-inode-is-pass.patch [bz#1694164]
- kvm-virtiofsd-Add-options-for-virtio.patch [bz#1694164]
- kvm-virtiofsd-add-o-source-PATH-to-help-output.patch [bz#1694164]
- kvm-virtiofsd-Open-vhost-connection-instead-of-mounting.patch [bz#1694164]
- kvm-virtiofsd-Start-wiring-up-vhost-user.patch [bz#1694164]
- kvm-virtiofsd-Add-main-virtio-loop.patch [bz#1694164]
- kvm-virtiofsd-get-set-features-callbacks.patch [bz#1694164]
- kvm-virtiofsd-Start-queue-threads.patch [bz#1694164]
- kvm-virtiofsd-Poll-kick_fd-for-queue.patch [bz#1694164]
- kvm-virtiofsd-Start-reading-commands-from-queue.patch [bz#1694164]
- kvm-virtiofsd-Send-replies-to-messages.patch [bz#1694164]
- kvm-virtiofsd-Keep-track-of-replies.patch [bz#1694164]
- kvm-virtiofsd-Add-Makefile-wiring-for-virtiofsd-contrib.patch [bz#1694164]
- kvm-virtiofsd-Fast-path-for-virtio-read.patch [bz#1694164]
- kvm-virtiofsd-add-fd-FDNUM-fd-passing-option.patch [bz#1694164]
- kvm-virtiofsd-make-f-foreground-the-default.patch [bz#1694164]
- kvm-virtiofsd-add-vhost-user.json-file.patch [bz#1694164]
- kvm-virtiofsd-add-print-capabilities-option.patch [bz#1694164]
- kvm-virtiofs-Add-maintainers-entry.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-create-new-files-in-caller-.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-add-lo_map-for-ino-fh-indir.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-add-ino_map-to-hide-lo_inod.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-add-dirp_map-to-hide-lo_dir.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-add-fd_map-to-hide-file-des.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-add-fallback-for-racy-ops.patch [bz#1694164]
- kvm-virtiofsd-validate-path-components.patch [bz#1694164]
- kvm-virtiofsd-Plumb-fuse_bufvec-through-to-do_write_buf.patch [bz#1694164]
- kvm-virtiofsd-Pass-write-iov-s-all-the-way-through.patch [bz#1694164]
- kvm-virtiofsd-add-fuse_mbuf_iter-API.patch [bz#1694164]
- kvm-virtiofsd-validate-input-buffer-sizes-in-do_write_bu.patch [bz#1694164]
- kvm-virtiofsd-check-input-buffer-size-in-fuse_lowlevel.c.patch [bz#1694164]
- kvm-virtiofsd-prevent-.-escape-in-lo_do_lookup.patch [bz#1694164]
- kvm-virtiofsd-prevent-.-escape-in-lo_do_readdir.patch [bz#1694164]
- kvm-virtiofsd-use-proc-self-fd-O_PATH-file-descriptor.patch [bz#1694164]
- kvm-virtiofsd-sandbox-mount-namespace.patch [bz#1694164]
- kvm-virtiofsd-move-to-an-empty-network-namespace.patch [bz#1694164]
- kvm-virtiofsd-move-to-a-new-pid-namespace.patch [bz#1694164]
- kvm-virtiofsd-add-seccomp-whitelist.patch [bz#1694164]
- kvm-virtiofsd-Parse-flag-FUSE_WRITE_KILL_PRIV.patch [bz#1694164]
- kvm-virtiofsd-cap-ng-helpers.patch [bz#1694164]
- kvm-virtiofsd-Drop-CAP_FSETID-if-client-asked-for-it.patch [bz#1694164]
- kvm-virtiofsd-set-maximum-RLIMIT_NOFILE-limit.patch [bz#1694164]
- kvm-virtiofsd-fix-libfuse-information-leaks.patch [bz#1694164]
- kvm-virtiofsd-add-syslog-command-line-option.patch [bz#1694164]
- kvm-virtiofsd-print-log-only-when-priority-is-high-enoug.patch [bz#1694164]
- kvm-virtiofsd-Add-ID-to-the-log-with-FUSE_LOG_DEBUG-leve.patch [bz#1694164]
- kvm-virtiofsd-Add-timestamp-to-the-log-with-FUSE_LOG_DEB.patch [bz#1694164]
- kvm-virtiofsd-Handle-reinit.patch [bz#1694164]
- kvm-virtiofsd-Handle-hard-reboot.patch [bz#1694164]
- kvm-virtiofsd-Kill-threads-when-queues-are-stopped.patch [bz#1694164]
- kvm-vhost-user-Print-unexpected-slave-message-types.patch [bz#1694164]
- kvm-contrib-libvhost-user-Protect-slave-fd-with-mutex.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-add-renameat2-support.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-disable-readdirplus-on-cach.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-control-readdirplus.patch [bz#1694164]
- kvm-virtiofsd-rename-unref_inode-to-unref_inode_lolocked.patch [bz#1694164]
- kvm-virtiofsd-fail-when-parent-inode-isn-t-known-in-lo_d.patch [bz#1694164]
- kvm-virtiofsd-extract-root-inode-init-into-setup_root.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-clean-up-cache-related-opti.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-use-hashtable.patch [bz#1694164]
- kvm-virtiofsd-Clean-up-inodes-on-destroy.patch [bz#1694164]
- kvm-virtiofsd-support-nanosecond-resolution-for-file-tim.patch [bz#1694164]
- kvm-virtiofsd-fix-error-handling-in-main.patch [bz#1694164]
- kvm-virtiofsd-cleanup-allocated-resource-in-se.patch [bz#1694164]
- kvm-virtiofsd-fix-memory-leak-on-lo.source.patch [bz#1694164]
- kvm-virtiofsd-add-helper-for-lo_data-cleanup.patch [bz#1694164]
- kvm-virtiofsd-Prevent-multiply-running-with-same-vhost_u.patch [bz#1694164]
- kvm-virtiofsd-enable-PARALLEL_DIROPS-during-INIT.patch [bz#1694164]
- kvm-virtiofsd-fix-incorrect-error-handling-in-lo_do_look.patch [bz#1694164]
- kvm-Virtiofsd-fix-memory-leak-on-fuse-queueinfo.patch [bz#1694164]
- kvm-virtiofsd-Support-remote-posix-locks.patch [bz#1694164]
- kvm-virtiofsd-use-fuse_lowlevel_is_virtio-in-fuse_sessio.patch [bz#1694164]
- kvm-virtiofsd-prevent-fv_queue_thread-vs-virtio_loop-rac.patch [bz#1694164]
- kvm-virtiofsd-make-lo_release-atomic.patch [bz#1694164]
- kvm-virtiofsd-prevent-races-with-lo_dirp_put.patch [bz#1694164]
- kvm-virtiofsd-rename-inode-refcount-to-inode-nlookup.patch [bz#1694164]
- kvm-libvhost-user-Fix-some-memtable-remap-cases.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-fix-refcounting-on-remove-r.patch [bz#1694164]
- kvm-virtiofsd-introduce-inode-refcount-to-prevent-use-af.patch [bz#1694164]
- kvm-virtiofsd-do-not-always-set-FUSE_FLOCK_LOCKS.patch [bz#1694164]
- kvm-virtiofsd-convert-more-fprintf-and-perror-to-use-fus.patch [bz#1694164]
- kvm-virtiofsd-Reset-O_DIRECT-flag-during-file-open.patch [bz#1694164]
- kvm-virtiofsd-Fix-data-corruption-with-O_APPEND-write-in.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-Use-cache_readdir-for-direc.patch [bz#1694164]
- kvm-virtiofsd-add-definition-of-fuse_buf_writev.patch [bz#1694164]
- kvm-virtiofsd-use-fuse_buf_writev-to-replace-fuse_buf_wr.patch [bz#1694164]
- kvm-virtiofsd-process-requests-in-a-thread-pool.patch [bz#1694164]
- kvm-virtiofsd-prevent-FUSE_INIT-FUSE_DESTROY-races.patch [bz#1694164]
- kvm-virtiofsd-fix-lo_destroy-resource-leaks.patch [bz#1694164]
- kvm-virtiofsd-add-thread-pool-size-NUM-option.patch [bz#1694164]
- kvm-virtiofsd-Convert-lo_destroy-to-take-the-lo-mutex-lo.patch [bz#1694164]
- kvm-virtiofsd-passthrough_ll-Pass-errno-to-fuse_reply_er.patch [bz#1694164]
- kvm-virtiofsd-stop-all-queue-threads-on-exit-in-virtio_l.patch [bz#1694164]
- kvm-virtiofsd-add-some-options-to-the-help-message.patch [bz#1694164]
- kvm-redhat-ship-virtiofsd-vhost-user-device-backend.patch [bz#1694164]
- Resolves: bz#1694164
  (virtio-fs: host<->guest shared file system (qemu))
- Resolves: bz#1725084
  (aarch64: support dumping SVE registers)
- Resolves: bz#1779041
  (netkvm: no connectivity Windows guest with q35 + hugepages + vhost + hv_synic)
2020-01-31 11:12:06 +01:00

1112 lines
35 KiB
Diff

From d6a0067e6c08523a8f605f775be980eaf0a23690 Mon Sep 17 00:00:00 2001
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Date: Mon, 27 Jan 2020 19:01:23 +0100
Subject: [PATCH 052/116] virtiofsd: check input buffer size in fuse_lowlevel.c
ops
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: <20200127190227.40942-49-dgilbert@redhat.com>
Patchwork-id: 93503
O-Subject: [RHEL-AV-8.2 qemu-kvm PATCH 048/112] virtiofsd: check input buffer size in fuse_lowlevel.c ops
Bugzilla: 1694164
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Acked-by: Sergio Lopez Pascual <slp@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>
Reviewed-by: Sergio Lopez <slp@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
(cherry picked from commit 70995754416eb4491c31607fe380a83cfd25a087)
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
tools/virtiofsd/fuse_lowlevel.c | 581 +++++++++++++++++++++++++++++++---------
1 file changed, 456 insertions(+), 125 deletions(-)
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index 611e8b0..02e1d83 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <errno.h>
#include <limits.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -27,7 +28,6 @@
#include <unistd.h>
-#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
#define OFFSET_MAX 0x7fffffffffffffffLL
struct fuse_pollhandle {
@@ -706,9 +706,14 @@ int fuse_reply_lseek(fuse_req_t req, off_t off)
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);
@@ -717,9 +722,16 @@ static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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);
@@ -729,20 +741,48 @@ 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);
+ return;
+ }
+
+ /*
+ * 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);
@@ -754,7 +794,7 @@ 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 {
@@ -762,12 +802,19 @@ 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;
- 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));
@@ -782,14 +829,21 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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) {
@@ -810,9 +864,16 @@ static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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);
@@ -821,9 +882,10 @@ static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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,10 +894,18 @@ static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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);
+ struct fuse_mknod_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;
+ }
req->ctx.umask = arg->umask;
@@ -846,22 +916,37 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
+ struct fuse_mkdir_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;
+ }
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);
@@ -870,9 +955,15 @@ static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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 +972,16 @@ static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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);
@@ -893,11 +990,20 @@ static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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, 0);
@@ -906,11 +1012,20 @@ static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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,
@@ -920,24 +1035,38 @@ static void do_rename2(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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) {
+ struct fuse_create_in *arg;
struct fuse_file_info fi;
- char *name = PARAM(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;
+ }
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
@@ -950,11 +1079,18 @@ static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -965,13 +1101,15 @@ static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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) {
+ struct fuse_read_in *arg;
struct fuse_file_info fi;
+ arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
fi.lock_owner = arg->lock_owner;
@@ -982,11 +1120,24 @@ static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
+ struct fuse_write_in *arg;
struct fuse_file_info fi;
- char *param;
+ const char *param;
+
+ arg = fuse_mbuf_iter_advance(iter, 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;
@@ -994,7 +1145,6 @@ static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
fi.lock_owner = arg->lock_owner;
fi.flags = arg->flags;
- param = PARAM(arg);
if (req->se->op.write) {
req->se->op.write(req, nodeid, param, arg->size, arg->offset, &fi);
@@ -1052,11 +1202,18 @@ 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;
+ struct fuse_flush_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.flush = 1;
@@ -1069,19 +1226,26 @@ static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
+ 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;
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 (req->se->op.release) {
@@ -1091,11 +1255,19 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -1111,11 +1283,18 @@ static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -1126,11 +1305,18 @@ static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -1141,11 +1327,18 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -1156,11 +1349,18 @@ static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -1172,11 +1372,19 @@ static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -1188,10 +1396,11 @@ static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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);
@@ -1204,11 +1413,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, arg->flags);
@@ -1217,20 +1440,36 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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);
@@ -1239,9 +1478,15 @@ static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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 +1510,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;
@@ -1284,12 +1536,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;
@@ -1327,14 +1585,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)
@@ -1379,12 +1639,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);
@@ -1425,9 +1693,15 @@ static struct fuse_req *check_interrupt(struct fuse_session *se,
}
}
-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);
@@ -1436,18 +1710,34 @@ static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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;
@@ -1468,11 +1758,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;
@@ -1496,11 +1793,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;
@@ -1513,12 +1817,17 @@ static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in,
- const void *inarg)
+ 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;
@@ -1535,11 +1844,17 @@ static void do_copy_file_range(fuse_req_t req, fuse_ino_t nodeid_in,
}
}
-static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+static void do_lseek(fuse_req_t req, fuse_ino_t nodeid,
+ struct fuse_mbuf_iter *iter)
{
- struct fuse_lseek_in *arg = (struct fuse_lseek_in *)inarg;
+ struct fuse_lseek_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;
@@ -1550,15 +1865,33 @@ static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
}
}
-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) {
@@ -1791,12 +2124,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) {
@@ -1976,7 +2310,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" },
@@ -2060,7 +2394,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;
@@ -2138,13 +2471,11 @@ void fuse_session_process_buf_int(struct fuse_session *se,
}
}
- 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:
--
1.8.3.1