From: Daniel Rosenberg <drosen@google.com>
To: Miklos Szeredi <miklos@szeredi.hu>,
bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>
Cc: Amir Goldstein <amir73il@gmail.com>,
linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-unionfs@vger.kernel.org,
Daniel Borkmann <daniel@iogearbox.net>,
John Fastabend <john.fastabend@gmail.com>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>, Yonghong Song <yhs@fb.com>,
KP Singh <kpsingh@kernel.org>,
Stanislav Fomichev <sdf@google.com>, Hao Luo <haoluo@google.com>,
Jiri Olsa <jolsa@kernel.org>, Shuah Khan <shuah@kernel.org>,
Jonathan Corbet <corbet@lwn.net>,
Joanne Koong <joannelkoong@gmail.com>,
Mykola Lysenko <mykolal@fb.com>,
kernel-team@android.com, Daniel Rosenberg <drosen@google.com>
Subject: [RFC PATCH v3 09/37] fuse-bpf: Add ioctl interface for /dev/fuse
Date: Mon, 17 Apr 2023 18:40:09 -0700 [thread overview]
Message-ID: <20230418014037.2412394-10-drosen@google.com> (raw)
In-Reply-To: <20230418014037.2412394-1-drosen@google.com>
This introduces an alternative method of responding to fuse requests.
Lookups supplying a backing fd or bpf will need to call through the
ioctl to ensure there can be no attempts to fool priveledged processes
into inadvertantly performing other actions.
Signed-off-by: Daniel Rosenberg <drosen@google.com>
---
fs/fuse/dev.c | 56 ++++++++++++++++++++++++++++++++-------
fs/fuse/fuse_i.h | 1 +
include/uapi/linux/fuse.h | 1 +
3 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index a3029824c24f..ad7d9d1e6da5 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1016,18 +1016,19 @@ static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
/* Copy the fuse-bpf lookup args and verify them */
#ifdef CONFIG_FUSE_BPF
-static int fuse_copy_lookup(struct fuse_copy_state *cs, void *val, unsigned size)
+static int fuse_copy_lookup(struct fuse_copy_state *cs, unsigned via_ioctl, void *val, unsigned size)
{
struct fuse_bpf_entry_out *fbeo = (struct fuse_bpf_entry_out *)val;
struct fuse_bpf_entry *feb = container_of(fbeo, struct fuse_bpf_entry, out[0]);
int num_entries = size / sizeof(*fbeo);
int err;
- if (size && size % sizeof(*fbeo) != 0)
+ if (size && (size % sizeof(*fbeo) != 0 || !via_ioctl))
return -EINVAL;
if (num_entries > FUSE_BPF_MAX_ENTRIES)
return -EINVAL;
+
err = fuse_copy_one(cs, val, size);
if (err)
return err;
@@ -1036,7 +1037,7 @@ static int fuse_copy_lookup(struct fuse_copy_state *cs, void *val, unsigned size
return err;
}
#else
-static int fuse_copy_lookup(struct fuse_copy_state *cs, void *val, unsigned size)
+static int fuse_copy_lookup(struct fuse_copy_state *cs, unsigned via_ioctl, void *val, unsigned size)
{
return fuse_copy_one(cs, val, size);
}
@@ -1045,7 +1046,7 @@ static int fuse_copy_lookup(struct fuse_copy_state *cs, void *val, unsigned size
/* Copy request arguments to/from userspace buffer */
static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
unsigned argpages, struct fuse_arg *args,
- int zeroing, unsigned is_lookup)
+ int zeroing, unsigned is_lookup, unsigned via_ioct)
{
int err = 0;
unsigned i;
@@ -1055,7 +1056,7 @@ static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
if (i == numargs - 1 && argpages)
err = fuse_copy_pages(cs, arg->size, zeroing);
else if (i == numargs - 1 && is_lookup)
- err = fuse_copy_lookup(cs, arg->value, arg->size);
+ err = fuse_copy_lookup(cs, via_ioct, arg->value, arg->size);
else
err = fuse_copy_one(cs, arg->value, arg->size);
}
@@ -1333,7 +1334,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
err = fuse_copy_one(cs, &req->in.h, sizeof(req->in.h));
if (!err)
err = fuse_copy_args(cs, args->in_numargs, args->in_pages,
- (struct fuse_arg *) args->in_args, 0, 0);
+ (struct fuse_arg *) args->in_args, 0, 0, 0);
fuse_copy_finish(cs);
spin_lock(&fpq->lock);
clear_bit(FR_LOCKED, &req->flags);
@@ -1872,7 +1873,8 @@ static int copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args,
lastarg->size -= diffsize;
}
return fuse_copy_args(cs, args->out_numargs, args->out_pages,
- args->out_args, args->page_zeroing, args->is_lookup);
+ args->out_args, args->page_zeroing, args->is_lookup,
+ args->via_ioctl);
}
/*
@@ -1882,7 +1884,7 @@ static int copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args,
* it from the list and copy the rest of the buffer to the request.
* The request is finished by calling fuse_request_end().
*/
-static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
+static ssize_t fuse_dev_do_write(struct fuse_dev *fud, bool from_ioctl,
struct fuse_copy_state *cs, size_t nbytes)
{
int err;
@@ -1954,6 +1956,7 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
if (!req->args->page_replace)
cs->move_pages = 0;
+ req->args->via_ioctl = from_ioctl;
if (oh.error)
err = nbytes != sizeof(oh) ? -EINVAL : 0;
else
@@ -1992,7 +1995,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from)
fuse_copy_init(&cs, 0, from);
- return fuse_dev_do_write(fud, &cs, iov_iter_count(from));
+ return fuse_dev_do_write(fud, false, &cs, iov_iter_count(from));
}
static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
@@ -2073,7 +2076,7 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
if (flags & SPLICE_F_MOVE)
cs.move_pages = 1;
- ret = fuse_dev_do_write(fud, &cs, len);
+ ret = fuse_dev_do_write(fud, false, &cs, len);
pipe_lock(pipe);
out_free:
@@ -2286,6 +2289,33 @@ static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
return 0;
}
+// Provides an alternate means to respond to a fuse request
+static int fuse_handle_ioc_response(struct fuse_dev *dev, void *buff, uint32_t size)
+{
+ struct fuse_copy_state cs;
+ struct iovec *iov = NULL;
+ struct iov_iter iter;
+ int res;
+
+ if (size > PAGE_SIZE)
+ return -EINVAL;
+ iov = (struct iovec *) __get_free_page(GFP_KERNEL);
+ if (!iov)
+ return -ENOMEM;
+
+ iov->iov_base = buff;
+ iov->iov_len = size;
+
+ iov_iter_init(&iter, READ, iov, 1, size);
+ fuse_copy_init(&cs, 0, &iter);
+
+
+ res = fuse_dev_do_write(dev, true, &cs, size);
+ free_page((unsigned long) iov);
+
+ return res;
+}
+
static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -2318,6 +2348,12 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
}
break;
default:
+ if (_IOC_TYPE(cmd) == FUSE_DEV_IOC_MAGIC
+ && _IOC_NR(cmd) == _IOC_NR(FUSE_DEV_IOC_BPF_RESPONSE(0))
+ && _IOC_DIR(cmd) == _IOC_WRITE) {
+ res = fuse_handle_ioc_response(fuse_get_dev(file), (void *) arg, _IOC_SIZE(cmd));
+ break;
+ }
res = -ENOTTY;
break;
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index c24878f4a89f..39a9fdf2a752 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -316,6 +316,7 @@ struct fuse_args {
bool may_block:1;
bool is_ext:1;
bool is_lookup:1;
+ bool via_ioctl:1;
struct fuse_in_arg in_args[3];
struct fuse_arg out_args[2];
void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 04d96f34e9a1..3ad725a3e968 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -1012,6 +1012,7 @@ struct fuse_notify_retrieve_in {
/* Device ioctls: */
#define FUSE_DEV_IOC_MAGIC 229
#define FUSE_DEV_IOC_CLONE _IOR(FUSE_DEV_IOC_MAGIC, 0, uint32_t)
+#define FUSE_DEV_IOC_BPF_RESPONSE(N) _IOW(FUSE_DEV_IOC_MAGIC, 125, char[N])
struct fuse_lseek_in {
uint64_t fh;
--
2.40.0.634.g4ca3ef3211-goog
next prev parent reply other threads:[~2023-04-18 1:42 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-18 1:40 [RFC PATCH bpf-next v3 00/37] FUSE BPF: A Stacked Filesystem Extension for FUSE Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 01/37] bpf: verifier: Accept dynptr mem as mem in herlpers Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 02/37] bpf: Allow NULL buffers in bpf_dynptr_slice(_rw) Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 03/37] selftests/bpf: Test allowing NULL buffer in dynptr slice Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 04/37] fs: Generic function to convert iocb to rw flags Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 05/37] fuse-bpf: Update fuse side uapi Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 06/37] fuse-bpf: Add data structures for fuse-bpf Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 07/37] fuse-bpf: Prepare for fuse-bpf patch Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 08/37] fuse: Add fuse-bpf, a stacked fs extension for FUSE Daniel Rosenberg
2023-05-02 3:38 ` Alexei Starovoitov
2023-05-03 3:45 ` Amir Goldstein
2023-04-18 1:40 ` Daniel Rosenberg [this message]
2023-04-18 1:40 ` [RFC PATCH v3 10/37] fuse-bpf: Don't support export_operations Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 11/37] fuse-bpf: Add support for access Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 12/37] fuse-bpf: Partially add mapping support Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 13/37] fuse-bpf: Add lseek support Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 14/37] fuse-bpf: Add support for fallocate Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 15/37] fuse-bpf: Support file/dir open/close Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 16/37] fuse-bpf: Support mknod/unlink/mkdir/rmdir Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 17/37] fuse-bpf: Add support for read/write iter Daniel Rosenberg
2023-05-16 20:21 ` Amir Goldstein
2023-04-18 1:40 ` [RFC PATCH v3 18/37] fuse-bpf: support readdir Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 19/37] fuse-bpf: Add support for sync operations Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 20/37] fuse-bpf: Add Rename support Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 21/37] fuse-bpf: Add attr support Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 22/37] fuse-bpf: Add support for FUSE_COPY_FILE_RANGE Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 23/37] fuse-bpf: Add xattr support Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 24/37] fuse-bpf: Add symlink/link support Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 25/37] fuse-bpf: allow mounting with no userspace daemon Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 26/37] bpf: Increase struct_op limits Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 27/37] fuse-bpf: Add fuse-bpf constants Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 28/37] WIP: bpf: Add fuse_ops struct_op programs Daniel Rosenberg
2023-04-27 4:18 ` Andrii Nakryiko
2023-05-03 1:53 ` Daniel Rosenberg
2023-05-03 18:22 ` Andrii Nakryiko
2023-04-18 1:40 ` [RFC PATCH v3 29/37] fuse-bpf: Export Functions Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 30/37] fuse: Provide registration functions for fuse-bpf Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 31/37] fuse-bpf: Set fuse_ops at mount or lookup time Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 32/37] fuse-bpf: Call bpf for pre/post filters Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 33/37] fuse-bpf: Add userspace " Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 34/37] WIP: fuse-bpf: add error_out Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 35/37] tools: Add FUSE, update bpf includes Daniel Rosenberg
2023-04-27 4:24 ` Andrii Nakryiko
2023-04-28 0:48 ` Daniel Rosenberg
2023-04-18 1:40 ` [RFC PATCH v3 37/37] fuse: Provide easy way to test fuse struct_op call Daniel Rosenberg
2023-04-18 5:33 ` [RFC PATCH bpf-next v3 00/37] FUSE BPF: A Stacked Filesystem Extension for FUSE Amir Goldstein
2023-04-21 1:41 ` Daniel Rosenberg
2023-04-23 14:50 ` Amir Goldstein
2023-04-24 15:32 ` Miklos Szeredi
2023-05-02 0:07 ` Daniel Rosenberg
2023-05-17 2:50 ` Gao Xiang
2023-05-17 6:51 ` Amir Goldstein
2023-05-17 7:05 ` Gao Xiang
2023-05-17 7:19 ` Gao Xiang
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=20230418014037.2412394-10-drosen@google.com \
--to=drosen@google.com \
--cc=amir73il@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=corbet@lwn.net \
--cc=daniel@iogearbox.net \
--cc=haoluo@google.com \
--cc=joannelkoong@gmail.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kernel-team@android.com \
--cc=kpsingh@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-unionfs@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=miklos@szeredi.hu \
--cc=mykolal@fb.com \
--cc=sdf@google.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=yhs@fb.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox