All of lore.kernel.org
 help / color / mirror / Atom feed
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>,  Eduard Zingerman <eddyz87@gmail.com>,
	Yonghong Song <yonghong.song@linux.dev>,
	 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>,
	 Christian Brauner <brauner@kernel.org>,
	kernel-team@android.com,  Daniel Rosenberg <drosen@google.com>
Subject: [RFC PATCH v4 26/36] WIP: bpf: Add fuse_ops struct_op programs
Date: Thu, 28 Mar 2024 18:53:41 -0700	[thread overview]
Message-ID: <20240329015351.624249-27-drosen@google.com> (raw)
In-Reply-To: <20240329015351.624249-1-drosen@google.com>

This introduces a new struct_op type: fuse_ops. This program set
provides pre and post filters to run around fuse-bpf calls that act
directly on the lower filesystem.

The inputs are either fixed structures, or struct fuse_buffer's.

These programs are not permitted to make any changes to these fuse_buffers
unless they create a dynptr wrapper using the supplied kfunc helpers.

Fuse_buffers maintain additional state information that FUSE uses to
manage memory and determine if additional set up or checks are needed.

Signed-off-by: Daniel Rosenberg <drosen@google.com>
---
 include/linux/bpf_fuse.h | 189 +++++++++++
 kernel/bpf/Makefile      |   4 +
 kernel/bpf/bpf_fuse.c    | 716 +++++++++++++++++++++++++++++++++++++++
 kernel/bpf/btf.c         |   1 +
 kernel/bpf/verifier.c    |  10 +-
 5 files changed, 919 insertions(+), 1 deletion(-)
 create mode 100644 kernel/bpf/bpf_fuse.c

diff --git a/include/linux/bpf_fuse.h b/include/linux/bpf_fuse.h
index ce8b1b347496..780a7889aea2 100644
--- a/include/linux/bpf_fuse.h
+++ b/include/linux/bpf_fuse.h
@@ -30,6 +30,8 @@ struct fuse_buffer {
 #define BPF_FUSE_MODIFIED	(1 << 3) // The helper function allowed writes to the buffer
 #define BPF_FUSE_ALLOCATED	(1 << 4) // The helper function allocated the buffer
 
+extern void *bpf_fuse_get_writeable(struct fuse_buffer *arg, u64 size, bool copy);
+
 /*
  * BPF Fuse Args
  *
@@ -81,4 +83,191 @@ static inline unsigned bpf_fuse_arg_size(const struct bpf_fuse_arg *arg)
 	return arg->is_buffer ? arg->buffer->size : arg->size;
 }
 
+struct fuse_ops {
+	uint32_t (*open_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_open_in *in);
+	uint32_t (*open_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_open_in *in,
+				struct fuse_open_out *out);
+
+	uint32_t (*opendir_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_open_in *in);
+	uint32_t (*opendir_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_open_in *in,
+				struct fuse_open_out *out);
+
+	uint32_t (*create_open_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_create_in *in, struct fuse_buffer *name);
+	uint32_t (*create_open_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_create_in *in, const struct fuse_buffer *name,
+				struct fuse_entry_out *entry_out, struct fuse_open_out *out);
+
+	uint32_t (*release_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_release_in *in);
+	uint32_t (*release_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_release_in *in);
+
+	uint32_t (*releasedir_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_release_in *in);
+	uint32_t (*releasedir_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_release_in *in);
+
+	uint32_t (*flush_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_flush_in *in);
+	uint32_t (*flush_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_flush_in *in);
+
+	uint32_t (*lseek_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_lseek_in *in);
+	uint32_t (*lseek_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_lseek_in *in,
+				struct fuse_lseek_out *out);
+
+	uint32_t (*copy_file_range_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_copy_file_range_in *in);
+	uint32_t (*copy_file_range_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_copy_file_range_in *in,
+				struct fuse_write_out *out);
+
+	uint32_t (*fsync_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_fsync_in *in);
+	uint32_t (*fsync_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_fsync_in *in);
+
+	uint32_t (*dir_fsync_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_fsync_in *in);
+	uint32_t (*dir_fsync_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_fsync_in *in);
+
+	uint32_t (*getxattr_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_getxattr_in *in, struct fuse_buffer *name);
+	// if in->size > 0, use value. If in->size == 0, use out.
+	uint32_t (*getxattr_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_getxattr_in *in, const struct fuse_buffer *name,
+				struct fuse_buffer *value, struct fuse_getxattr_out *out);
+
+	uint32_t (*listxattr_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_getxattr_in *in);
+	// if in->size > 0, use value. If in->size == 0, use out.
+	uint32_t (*listxattr_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_getxattr_in *in,
+				struct fuse_buffer *value, struct fuse_getxattr_out *out);
+
+	uint32_t (*setxattr_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_setxattr_in *in, struct fuse_buffer *name,
+					struct fuse_buffer *value);
+	uint32_t (*setxattr_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_setxattr_in *in, const struct fuse_buffer *name,
+					const struct fuse_buffer *value);
+
+	uint32_t (*removexattr_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name);
+	uint32_t (*removexattr_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name);
+
+	/* Read and Write iter will likely undergo some sort of change/addition to handle changing
+	 * the data buffer passed in/out. */
+	uint32_t (*read_iter_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_read_in *in);
+	uint32_t (*read_iter_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_read_in *in,
+				struct fuse_read_iter_out *out);
+
+	uint32_t (*write_iter_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_write_in *in);
+	uint32_t (*write_iter_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_write_in *in,
+				struct fuse_write_iter_out *out);
+
+	uint32_t (*file_fallocate_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_fallocate_in *in);
+	uint32_t (*file_fallocate_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_fallocate_in *in);
+
+	uint32_t (*lookup_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name);
+	uint32_t (*lookup_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name,
+				struct fuse_entry_out *out, struct fuse_buffer *entries);
+
+	uint32_t (*mknod_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_mknod_in *in, struct fuse_buffer *name);
+	uint32_t (*mknod_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_mknod_in *in, const struct fuse_buffer *name);
+
+	uint32_t (*mkdir_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_mkdir_in *in, struct fuse_buffer *name);
+	uint32_t (*mkdir_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_mkdir_in *in, const struct fuse_buffer *name);
+
+	uint32_t (*rmdir_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name);
+	uint32_t (*rmdir_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name);
+
+	uint32_t (*rename2_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_rename2_in *in, struct fuse_buffer *old_name,
+				struct fuse_buffer *new_name);
+	uint32_t (*rename2_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_rename2_in *in, const struct fuse_buffer *old_name,
+				const struct fuse_buffer *new_name);
+
+	uint32_t (*rename_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_rename_in *in, struct fuse_buffer *old_name,
+				struct fuse_buffer *new_name);
+	uint32_t (*rename_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_rename_in *in, const struct fuse_buffer *old_name,
+				const struct fuse_buffer *new_name);
+
+	uint32_t (*unlink_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name);
+	uint32_t (*unlink_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name);
+
+	uint32_t (*link_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_link_in *in, struct fuse_buffer *name);
+	uint32_t (*link_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_link_in *in, const struct fuse_buffer *name);
+
+	uint32_t (*getattr_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_getattr_in *in);
+	uint32_t (*getattr_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_getattr_in *in,
+				struct fuse_attr_out *out);
+
+	uint32_t (*setattr_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_setattr_in *in);
+	uint32_t (*setattr_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_setattr_in *in,
+				struct fuse_attr_out *out);
+
+	uint32_t (*statfs_prefilter)(const struct bpf_fuse_meta_info *meta);
+	uint32_t (*statfs_postfilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_statfs_out *out);
+
+	//TODO: This does not allow doing anything with path
+	uint32_t (*get_link_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name);
+	uint32_t (*get_link_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name);
+
+	uint32_t (*symlink_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name, struct fuse_buffer *path);
+	uint32_t (*symlink_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name, const struct fuse_buffer *path);
+
+	uint32_t (*readdir_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_read_in *in);
+	uint32_t (*readdir_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_read_in *in,
+				struct fuse_read_out *out, struct fuse_buffer *buffer);
+
+	uint32_t (*access_prefilter)(const struct bpf_fuse_meta_info *meta,
+				struct fuse_access_in *in);
+	uint32_t (*access_postfilter)(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_access_in *in);
+
+	char name[BPF_FUSE_NAME_MAX];
+};
+
 #endif /* _BPF_FUSE_H */
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index 4ce95acfcaa7..1fc22dfc8bee 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -46,3 +46,7 @@ obj-$(CONFIG_BPF_PRELOAD) += preload/
 obj-$(CONFIG_BPF_SYSCALL) += relo_core.o
 $(obj)/relo_core.o: $(srctree)/tools/lib/bpf/relo_core.c FORCE
 	$(call if_changed_rule,cc_o_c)
+
+ifeq ($(CONFIG_FUSE_BPF),y)
+obj-$(CONFIG_BPF_SYSCALL) += bpf_fuse.o
+endif
diff --git a/kernel/bpf/bpf_fuse.c b/kernel/bpf/bpf_fuse.c
new file mode 100644
index 000000000000..7ae93b5230c7
--- /dev/null
+++ b/kernel/bpf/bpf_fuse.c
@@ -0,0 +1,716 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2021 Google LLC
+
+#include <linux/filter.h>
+#include <linux/bpf.h>
+#include <linux/bpf_fuse.h>
+#include <linux/bpf_verifier.h>
+#include <linux/btf.h>
+
+void *bpf_fuse_get_writeable(struct fuse_buffer *arg, u64 size, bool copy)
+{
+	void *writeable_val;
+
+	if (arg->flags & BPF_FUSE_IMMUTABLE)
+		return 0;
+
+	if (size <= arg->size &&
+			(!(arg->flags & BPF_FUSE_MUST_ALLOCATE) ||
+			  (arg->flags & BPF_FUSE_ALLOCATED))) {
+		if (arg->flags & BPF_FUSE_VARIABLE_SIZE)
+			arg->size = size;
+		arg->flags |= BPF_FUSE_MODIFIED;
+		return arg->data;
+	}
+	/* Variable sized arrays must stay below max size. If the buffer must be fixed size,
+	 * don't change the allocated size. Verifier will enforce requested size for accesses
+	 */
+	if (arg->flags & BPF_FUSE_VARIABLE_SIZE) {
+		if (size > arg->max_size)
+			return 0;
+	} else {
+		if (size > arg->size)
+			return 0;
+		size = arg->size;
+	}
+
+	if (size != arg->size && size > arg->max_size)
+		return 0;
+
+	/* If our buffer is big enough, just adjust size */
+	if (size <= arg->alloc_size) {
+		if (!copy)
+			arg->size = size;
+		arg->flags |= BPF_FUSE_MODIFIED;
+		return arg->data;
+	}
+
+	writeable_val = kzalloc(size, GFP_KERNEL);
+	if (!writeable_val)
+		return 0;
+
+	arg->alloc_size = size;
+	/* If we're copying the buffer, assume the same amount is used. If that isn't the case,
+	 * caller must change size. Otherwise, assume entirety of new buffer is used.
+	 */
+	if (copy)
+		memcpy(writeable_val, arg->data, (arg->size > size) ? size : arg->size);
+	else
+		arg->size = size;
+
+	if (arg->flags & BPF_FUSE_ALLOCATED)
+		kfree(arg->data);
+	arg->data = writeable_val;
+
+	arg->flags |= BPF_FUSE_ALLOCATED | BPF_FUSE_MODIFIED;
+
+	return arg->data;
+}
+EXPORT_SYMBOL(bpf_fuse_get_writeable);
+
+__bpf_kfunc_start_defs();
+__bpf_kfunc void bpf_fuse_get_rw_dynptr(struct fuse_buffer *buffer, struct bpf_dynptr_kern *dynptr__uninit, u64 size, bool copy)
+{
+	buffer->data = bpf_fuse_get_writeable(buffer, size, copy);
+	bpf_dynptr_init(dynptr__uninit, buffer->data, BPF_DYNPTR_TYPE_LOCAL, 0, buffer->size);
+}
+
+__bpf_kfunc void bpf_fuse_get_ro_dynptr(const struct fuse_buffer *buffer, struct bpf_dynptr_kern *dynptr__uninit)
+{
+	bpf_dynptr_init(dynptr__uninit, buffer->data, BPF_DYNPTR_TYPE_LOCAL, 0, buffer->size);
+	bpf_dynptr_set_rdonly(dynptr__uninit);
+}
+
+__bpf_kfunc uint32_t bpf_fuse_return_len(struct fuse_buffer *buffer)
+{
+	return buffer->size;
+}
+__diag_pop();
+__bpf_kfunc_end_defs();
+BTF_KFUNCS_START(fuse_kfunc_set)
+BTF_ID_FLAGS(func, bpf_fuse_get_rw_dynptr)
+BTF_ID_FLAGS(func, bpf_fuse_get_ro_dynptr)
+BTF_ID_FLAGS(func, bpf_fuse_return_len)
+BTF_KFUNCS_END(fuse_kfunc_set)
+
+static const struct btf_kfunc_id_set bpf_fuse_kfunc_set = {
+	.owner = THIS_MODULE,
+	.set = &fuse_kfunc_set,
+};
+
+static const struct bpf_func_proto *bpf_fuse_get_func_proto(enum bpf_func_id func_id,
+							      const struct bpf_prog *prog)
+{
+	switch (func_id) {
+	default:
+		return bpf_base_func_proto(func_id, prog);
+	}
+}
+
+static bool bpf_fuse_is_valid_access(int off, int size,
+				    enum bpf_access_type type,
+				    const struct bpf_prog *prog,
+				    struct bpf_insn_access_aux *info)
+{
+	return bpf_tracing_btf_ctx_access(off, size, type, prog, info);
+}
+
+const struct btf_type *fuse_buffer_struct_type;
+
+static int bpf_fuse_btf_struct_access(struct bpf_verifier_log *log,
+					const struct bpf_reg_state *reg,
+					int off, int size)
+{
+	const struct btf_type *t;
+
+	t = btf_type_by_id(reg->btf, reg->btf_id);
+	if (t == fuse_buffer_struct_type) {
+		bpf_log(log,
+			"direct access to fuse_buffer is disallowed\n");
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+static const struct bpf_verifier_ops bpf_fuse_verifier_ops = {
+	.get_func_proto		= bpf_fuse_get_func_proto,
+	.is_valid_access	= bpf_fuse_is_valid_access,
+	.btf_struct_access	= bpf_fuse_btf_struct_access,
+};
+
+static int bpf_fuse_check_member(const struct btf_type *t,
+				   const struct btf_member *member,
+				   const struct bpf_prog *prog)
+{
+	//if (is_unsupported(__btf_member_bit_offset(t, member) / 8))
+	//	return -ENOTSUPP;
+	return 0;
+}
+
+static int bpf_fuse_init_member(const struct btf_type *t,
+				  const struct btf_member *member,
+				  void *kdata, const void *udata)
+{
+	const struct fuse_ops *uf_ops;
+	struct fuse_ops *f_ops;
+	u32 moff;
+
+	uf_ops = (const struct fuse_ops *)udata;
+	f_ops = (struct fuse_ops *)kdata;
+
+	moff = __btf_member_bit_offset(t, member) / 8;
+	switch (moff) {
+	case offsetof(struct fuse_ops, name):
+		if (bpf_obj_name_cpy(f_ops->name, uf_ops->name,
+				     sizeof(f_ops->name)) <= 0)
+			return -EINVAL;
+		return 1;
+	}
+
+	return 0;
+}
+
+static int bpf_fuse_init(struct btf *btf)
+{
+	s32 type_id;
+
+	type_id = btf_find_by_name_kind(btf, "fuse_buffer", BTF_KIND_STRUCT);
+	if (type_id < 0)
+		return -EINVAL;
+	fuse_buffer_struct_type = btf_type_by_id(btf, type_id);
+
+	return 0;
+}
+
+static struct bpf_fuse_ops_attach *fuse_reg = NULL;
+
+static int bpf_fuse_reg(void *kdata)
+{
+	if (fuse_reg)
+		return fuse_reg->fuse_register_bpf(kdata);
+	pr_warn("Cannot register fuse_ops, FUSE not found");
+	return -EOPNOTSUPP;
+}
+
+static void bpf_fuse_unreg(void *kdata)
+{
+	if(fuse_reg)
+		return fuse_reg->fuse_unregister_bpf(kdata);
+}
+
+int register_fuse_bpf(struct bpf_fuse_ops_attach *reg_ops)
+{
+	fuse_reg = reg_ops;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(register_fuse_bpf);
+
+void unregister_fuse_bpf(struct bpf_fuse_ops_attach *reg_ops)
+{
+	if (reg_ops == fuse_reg)
+		fuse_reg = NULL;
+	else
+		pr_warn("Refusing to unregister unregistered FUSE");
+}
+EXPORT_SYMBOL_GPL(unregister_fuse_bpf);
+
+/* CFI Stubs */
+static uint32_t bpf_fuse_default_filter(const struct bpf_fuse_meta_info *meta)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_open_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_open_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_open_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_open_in *in,
+				struct fuse_open_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_opendir_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_open_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_opendir_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_open_in *in,
+				struct fuse_open_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_create_open_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_create_in *in, struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_create_open_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_create_in *in, const struct fuse_buffer *name,
+				struct fuse_entry_out *entry_out, struct fuse_open_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_release_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_release_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_release_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_release_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_releasedir_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_release_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_releasedir_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_release_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_flush_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_flush_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_flush_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_flush_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_lseek_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_lseek_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_lseek_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_lseek_in *in,
+				struct fuse_lseek_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_copy_file_range_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_copy_file_range_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_copy_file_range_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_copy_file_range_in *in,
+				struct fuse_write_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_fsync_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_fsync_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_fsync_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_fsync_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_dir_fsync_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_fsync_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_dir_fsync_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_fsync_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_getxattr_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_getxattr_in *in, struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_getxattr_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_getxattr_in *in, const struct fuse_buffer *name,
+				struct fuse_buffer *value, struct fuse_getxattr_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_listxattr_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_getxattr_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_listxattr_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_getxattr_in *in,
+				struct fuse_buffer *value, struct fuse_getxattr_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_setxattr_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_setxattr_in *in, struct fuse_buffer *name,
+					struct fuse_buffer *value)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_setxattr_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_setxattr_in *in, const struct fuse_buffer *name,
+					const struct fuse_buffer *value)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_removexattr_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_removexattr_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_read_iter_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_read_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_read_iter_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_read_in *in,
+				struct fuse_read_iter_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_write_iter_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_write_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_write_iter_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_write_in *in,
+				struct fuse_write_iter_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_file_fallocate_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_fallocate_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_file_fallocate_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_fallocate_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_lookup_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_lookup_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name,
+				struct fuse_entry_out *out, struct fuse_buffer *entries)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_mknod_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_mknod_in *in, struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_mknod_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_mknod_in *in, const struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_mkdir_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_mkdir_in *in, struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_mkdir_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_mkdir_in *in, const struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_rmdir_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_rmdir_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_rename2_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_rename2_in *in, struct fuse_buffer *old_name,
+				struct fuse_buffer *new_name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_rename2_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_rename2_in *in, const struct fuse_buffer *old_name,
+				const struct fuse_buffer *new_name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_rename_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_rename_in *in, struct fuse_buffer *old_name,
+				struct fuse_buffer *new_name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_rename_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_rename_in *in, const struct fuse_buffer *old_name,
+				const struct fuse_buffer *new_name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_unlink_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_unlink_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_link_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_link_in *in, struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_link_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_link_in *in, const struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_getattr_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_getattr_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_getattr_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_getattr_in *in,
+				struct fuse_attr_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_setattr_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_setattr_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_setattr_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_setattr_in *in,
+				struct fuse_attr_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_statfs_prefilter(const struct bpf_fuse_meta_info *meta)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_statfs_postfilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_statfs_out *out)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_get_link_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_get_link_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_symlink_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_buffer *name, struct fuse_buffer *path)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_symlink_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_buffer *name, const struct fuse_buffer *path)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_readdir_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_read_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_readdir_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_read_in *in,
+				struct fuse_read_out *out, struct fuse_buffer *buffer)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_access_prefilter(const struct bpf_fuse_meta_info *meta,
+				struct fuse_access_in *in)
+{
+	return 0;
+}
+
+static uint32_t bpf_fuse_access_postfilter(const struct bpf_fuse_meta_info *meta,
+				const struct fuse_access_in *in)
+{
+	return 0;
+}
+
+static struct fuse_ops __bpf_fuse_ops = {
+	.default_filter = bpf_fuse_default_filter,
+	.open_prefilter = bpf_fuse_open_prefilter,
+	.open_postfilter = bpf_fuse_open_postfilter,
+	.opendir_prefilter = bpf_fuse_opendir_prefilter,
+	.opendir_postfilter = bpf_fuse_opendir_postfilter,
+	.create_open_prefilter = bpf_fuse_create_open_prefilter,
+	.create_open_postfilter = bpf_fuse_create_open_postfilter,
+	.release_prefilter = bpf_fuse_release_prefilter,
+	.release_postfilter = bpf_fuse_release_postfilter,
+	.releasedir_prefilter = bpf_fuse_releasedir_prefilter,
+	.releasedir_postfilter = bpf_fuse_releasedir_postfilter,
+	.flush_prefilter = bpf_fuse_flush_prefilter,
+	.flush_postfilter = bpf_fuse_flush_postfilter,
+	.lseek_prefilter = bpf_fuse_lseek_prefilter,
+	.lseek_postfilter = bpf_fuse_lseek_postfilter,
+	.copy_file_range_prefilter = bpf_fuse_copy_file_range_prefilter,
+	.copy_file_range_postfilter = bpf_fuse_copy_file_range_postfilter,
+	.fsync_prefilter = bpf_fuse_fsync_prefilter,
+	.fsync_postfilter = bpf_fuse_fsync_postfilter,
+	.dir_fsync_prefilter = bpf_fuse_dir_fsync_prefilter,
+	.dir_fsync_postfilter = bpf_fuse_dir_fsync_postfilter,
+	.getxattr_prefilter = bpf_fuse_getxattr_prefilter,
+	.getxattr_postfilter = bpf_fuse_getxattr_postfilter,
+	.listxattr_prefilter = bpf_fuse_listxattr_prefilter,
+	.listxattr_postfilter = bpf_fuse_listxattr_postfilter,
+	.setxattr_prefilter = bpf_fuse_setxattr_prefilter,
+	.setxattr_postfilter = bpf_fuse_setxattr_postfilter,
+	.removexattr_prefilter = bpf_fuse_removexattr_prefilter,
+	.removexattr_postfilter = bpf_fuse_removexattr_postfilter,
+	.read_iter_prefilter = bpf_fuse_read_iter_prefilter,
+	.read_iter_postfilter = bpf_fuse_read_iter_postfilter,
+	.write_iter_prefilter = bpf_fuse_write_iter_prefilter,
+	.write_iter_postfilter = bpf_fuse_write_iter_postfilter,
+	.file_fallocate_prefilter = bpf_fuse_file_fallocate_prefilter,
+	.file_fallocate_postfilter = bpf_fuse_file_fallocate_postfilter,
+	.lookup_prefilter = bpf_fuse_lookup_prefilter,
+	.lookup_postfilter = bpf_fuse_lookup_postfilter,
+	.mknod_prefilter = bpf_fuse_mknod_prefilter,
+	.mknod_postfilter = bpf_fuse_mknod_postfilter,
+	.mkdir_prefilter = bpf_fuse_mkdir_prefilter,
+	.mkdir_postfilter = bpf_fuse_mkdir_postfilter,
+	.rmdir_prefilter = bpf_fuse_rmdir_prefilter,
+	.rmdir_postfilter = bpf_fuse_rmdir_postfilter,
+	.rename2_prefilter = bpf_fuse_rename2_prefilter,
+	.rename2_postfilter = bpf_fuse_rename2_postfilter,
+	.rename_prefilter = bpf_fuse_rename_prefilter,
+	.rename_postfilter = bpf_fuse_rename_postfilter,
+	.unlink_prefilter = bpf_fuse_unlink_prefilter,
+	.unlink_postfilter = bpf_fuse_unlink_postfilter,
+	.link_prefilter = bpf_fuse_link_prefilter,
+	.link_postfilter = bpf_fuse_link_postfilter,
+	.getattr_prefilter = bpf_fuse_getattr_prefilter,
+	.getattr_postfilter = bpf_fuse_getattr_postfilter,
+	.setattr_prefilter = bpf_fuse_setattr_prefilter,
+	.setattr_postfilter = bpf_fuse_setattr_postfilter,
+	.statfs_prefilter = bpf_fuse_statfs_prefilter,
+	.statfs_postfilter = bpf_fuse_statfs_postfilter,
+	.get_link_prefilter = bpf_fuse_get_link_prefilter,
+	.get_link_postfilter = bpf_fuse_get_link_postfilter,
+	.symlink_prefilter = bpf_fuse_symlink_prefilter,
+	.symlink_postfilter = bpf_fuse_symlink_postfilter,
+	.readdir_prefilter = bpf_fuse_readdir_prefilter,
+	.readdir_postfilter = bpf_fuse_readdir_postfilter,
+	.access_prefilter = bpf_fuse_access_prefilter,
+	.access_postfilter = bpf_fuse_access_postfilter,
+};
+
+static struct bpf_struct_ops bpf_fuse_ops = {
+	.verifier_ops = &bpf_fuse_verifier_ops,
+	.reg = bpf_fuse_reg,
+	.unreg = bpf_fuse_unreg,
+	.check_member = bpf_fuse_check_member,
+	.init_member = bpf_fuse_init_member,
+	.init = bpf_fuse_init,
+	.name = "fuse_ops",
+	.cfi_stubs = &__bpf_fuse_ops,
+	.owner = THIS_MODULE,
+};
+
+static int __init bpf_fuse_ops_init(void)
+{
+	int ret;
+
+	ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,
+					 &bpf_fuse_kfunc_set);
+	ret = ret ?: register_bpf_struct_ops(&bpf_fuse_ops, fuse_ops);
+
+	return ret;
+}
+late_initcall(bpf_fuse_ops_init);
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 170d017e8e4a..29f7db457127 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -26,6 +26,7 @@
 #include <linux/bsearch.h>
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
+#include <linux/bpf_fuse.h>
 
 #include <net/netfilter/nf_bpf_link.h>
 
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index ee86e4d7d5fc..eb0808ed3cd9 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -10947,6 +10947,8 @@ enum special_kfunc_type {
 	KF_bpf_percpu_obj_drop_impl,
 	KF_bpf_throw,
 	KF_bpf_iter_css_task_new,
+	KF_bpf_fuse_get_rw_dynptr,
+	KF_bpf_fuse_get_ro_dynptr,
 };
 
 BTF_SET_START(special_kfunc_set)
@@ -10973,6 +10975,8 @@ BTF_ID(func, bpf_throw)
 #ifdef CONFIG_CGROUPS
 BTF_ID(func, bpf_iter_css_task_new)
 #endif
+BTF_ID(func, bpf_fuse_get_rw_dynptr)
+BTF_ID(func, bpf_fuse_get_ro_dynptr)
 BTF_SET_END(special_kfunc_set)
 
 BTF_ID_LIST(special_kfunc_list)
@@ -11003,6 +11007,8 @@ BTF_ID(func, bpf_iter_css_task_new)
 #else
 BTF_ID_UNUSED
 #endif
+BTF_ID(func, bpf_fuse_get_rw_dynptr)
+BTF_ID(func, bpf_fuse_get_ro_dynptr)
 
 static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta)
 {
@@ -11793,7 +11799,9 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
 					verbose(env, "verifier internal error: missing ref obj id for parent of clone\n");
 					return -EFAULT;
 				}
-			}
+			} else if (meta->func_id == special_kfunc_list[KF_bpf_fuse_get_rw_dynptr] ||
+					meta->func_id == special_kfunc_list[KF_bpf_fuse_get_ro_dynptr])
+				dynptr_arg_type |= DYNPTR_TYPE_LOCAL;
 
 			ret = process_dynptr_func(env, regno, insn_idx, dynptr_arg_type, clone_ref_obj_id);
 			if (ret < 0)
-- 
2.44.0.478.gd926399ef9-goog


  parent reply	other threads:[~2024-03-29  1:54 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-29  1:53 [RFC PATCH v4 00/36] Fuse-BPF and plans on merging with Fuse Passthrough Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 01/36] fuse-bpf: Update fuse side uapi Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 02/36] fuse-bpf: Add data structures for fuse-bpf Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 03/36] fuse-bpf: Prepare for fuse-bpf patch Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 04/36] fuse: Add fuse-bpf, a stacked fs extension for FUSE Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 05/36] fuse-bpf: Add ioctl interface for /dev/fuse Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 06/36] fuse-bpf: Don't support export_operations Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 07/36] fuse-bpf: Add support for access Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 08/36] fuse-bpf: Partially add mapping support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 09/36] fuse-bpf: Add lseek support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 10/36] fuse-bpf: Add support for fallocate Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 11/36] fuse-bpf: Support file/dir open/close Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 12/36] fuse-bpf: Support mknod/unlink/mkdir/rmdir Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 13/36] fuse-bpf: Add support for read/write iter Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 14/36] fuse-bpf: support readdir Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 15/36] fuse-bpf: Add support for sync operations Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 16/36] fuse-bpf: Add Rename support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 17/36] fuse-bpf: Add attr support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 18/36] fuse-bpf: Add support for FUSE_COPY_FILE_RANGE Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 19/36] fuse-bpf: Add xattr support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 20/36] fuse-bpf: Add symlink/link support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 21/36] fuse-bpf: Add partial flock support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 22/36] fuse-bpf: Add partial ioctl support Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 23/36] fuse-bpf: allow mounting with no userspace daemon Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 24/36] fuse-bpf: Add fuse-bpf constants Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 25/36] bpf: Increase struct_op max members Daniel Rosenberg
2024-03-29  1:53 ` Daniel Rosenberg [this message]
2024-03-29  1:53 ` [RFC PATCH v4 27/36] fuse-bpf: Export Functions Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 28/36] fuse: Provide registration functions for fuse-bpf Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 29/36] fuse-bpf: Set fuse_ops at mount or lookup time Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 30/36] fuse-bpf: Call bpf for pre/post filters Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 31/36] fuse-bpf: Add userspace " Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 32/36] WIP: fuse-bpf: add error_out Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 33/36] fuse-bpf: Add default filter op Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 34/36] tools: Add FUSE, update bpf includes Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 35/36] fuse-bpf: Add selftests Daniel Rosenberg
2024-03-29  1:53 ` [RFC PATCH v4 36/36] fuse: Provide easy way to test fuse struct_op call Daniel Rosenberg
2024-03-29  6:44 ` [RFC PATCH v4 00/36] Fuse-BPF and plans on merging with Fuse Passthrough Amir Goldstein
2024-03-30  0:59   ` Daniel Rosenberg
2024-04-01 14:43     ` Amir Goldstein
2024-04-01 20:27       ` Bernd Schubert

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=20240329015351.624249-27-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=brauner@kernel.org \
    --cc=corbet@lwn.net \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --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=yonghong.song@linux.dev \
    /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.