[RFC PATCH bpf-next v3 00/37] FUSE BPF: A Stacked Filesystem Extension for FUSE

From: Daniel Rosenberg
Date: Mon Apr 17 2023 - 21:41:02 EST


These patches extend FUSE to be able to act as a stacked filesystem. This
allows pure passthrough, where the fuse file system simply reflects the lower
filesystem, and also allows optional pre and post filtering in BPF and/or the
userspace daemon as needed. This can dramatically reduce or even eliminate
transitions to and from userspace.

In this patch set, I've reworked the bpf code to add a new struct_op type
instead of a new program type, and used new kfuncs in place of new helpers.
Additionally, it now uses dynptrs for variable sized buffers. The first three
patches are repeats of a previous patch set which I have not yet adjusted for
comments. I plan to adjust those and submit them separately with fixes, but
wanted to have the current fuse-bpf code visible before then.

Patches 4-7 mostly rearrange existing code to remove noise from the main patch.
Patch 8 contains the main sections of fuse-bpf
Patches 9-25 implementing most FUSE functions as operations on a lower
filesystem. From patch 25, you can run fuse as a passthrough filesystem.
Patches 26-32 provide bpf functionality so that you can alter fuse parameters
via fuse_op programs.
Patch 33 extends this to userspace, and patches 34-37 add some testing
functionality.

There's definitely a lot of cleanup and some restructuring I would like to do.
In the current form, I could get rid of the large macro in place of a function
that takes a struct that groups a bunch of function pointers, although I'm not
sure a function that takes three void*'s is much better than the macro... I'm
definitely open to suggestions on how to clean that up.

This changes the format of adding a backing file/bpf slightly from v2. fuse_op
programs are specified by name, limited to 15 characters. The block added to
fuse_bpf_entires has been increased to compensate. This adds one more unused
field when specifying the backing file.

Lookups responses that add a backing file must go through an ioctl interface.
This is to prevent any attempts at fooling priveledged programs with fd
trickery.

Currently, there are two types of fuse_bpf_entry. One for passing the fuse_op
program you wish to use, specified by name, and one for passing the fd of the
backing file you'd like to associate with the given lookup. In the future, this
may be extended to a more complicated system allowing for multiple bpf programs
or backing files. This would come with kfuncs for bpf to indicate which backing
file should be acted upon. Multiple bpf programs would allow chaining existing
programs to extend functionality without requiring an entirely new program set.

You can run this without needing to set up a userspace daemon by adding these
mount options: root_dir=[fd],no_daemon where fd is an open file descriptor
pointing to the folder you'd like to use as the root directory. The fd can be
immediately closed after mounting. You may also set a root_bpf program by
setting root_bpf=[fuse_op name] after registering a fuse_op program.
This is useful for running various fs tests.

This patch set is against bpf-next

The main changes for v3:
Restructured around struct_op programs
Using dynptrs instead of packets
Using kfuncs instead of new helpers
Selftests now use skel for loading

Alessio Balsini (1):
fs: Generic function to convert iocb to rw flags

Daniel Rosenberg (36):
bpf: verifier: Accept dynptr mem as mem in herlpers
bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)
selftests/bpf: Test allowing NULL buffer in dynptr slice
fuse-bpf: Update fuse side uapi
fuse-bpf: Add data structures for fuse-bpf
fuse-bpf: Prepare for fuse-bpf patch
fuse: Add fuse-bpf, a stacked fs extension for FUSE
fuse-bpf: Add ioctl interface for /dev/fuse
fuse-bpf: Don't support export_operations
fuse-bpf: Add support for access
fuse-bpf: Partially add mapping support
fuse-bpf: Add lseek support
fuse-bpf: Add support for fallocate
fuse-bpf: Support file/dir open/close
fuse-bpf: Support mknod/unlink/mkdir/rmdir
fuse-bpf: Add support for read/write iter
fuse-bpf: support readdir
fuse-bpf: Add support for sync operations
fuse-bpf: Add Rename support
fuse-bpf: Add attr support
fuse-bpf: Add support for FUSE_COPY_FILE_RANGE
fuse-bpf: Add xattr support
fuse-bpf: Add symlink/link support
fuse-bpf: allow mounting with no userspace daemon
bpf: Increase struct_op limits
fuse-bpf: Add fuse-bpf constants
WIP: bpf: Add fuse_ops struct_op programs
fuse-bpf: Export Functions
fuse: Provide registration functions for fuse-bpf
fuse-bpf: Set fuse_ops at mount or lookup time
fuse-bpf: Call bpf for pre/post filters
fuse-bpf: Add userspace pre/post filters
WIP: fuse-bpf: add error_out
tools: Add FUSE, update bpf includes
fuse-bpf: Add selftests
fuse: Provide easy way to test fuse struct_op call

Documentation/bpf/kfuncs.rst | 23 +-
fs/fuse/Kconfig | 8 +
fs/fuse/Makefile | 1 +
fs/fuse/backing.c | 4241 +++++++++++++++++
fs/fuse/bpf_register.c | 209 +
fs/fuse/control.c | 2 +-
fs/fuse/dev.c | 85 +-
fs/fuse/dir.c | 344 +-
fs/fuse/file.c | 63 +-
fs/fuse/fuse_i.h | 495 +-
fs/fuse/inode.c | 360 +-
fs/fuse/ioctl.c | 2 +-
fs/fuse/readdir.c | 5 +
fs/fuse/xattr.c | 18 +
fs/overlayfs/file.c | 23 +-
include/linux/bpf.h | 2 +-
include/linux/bpf_fuse.h | 283 ++
include/linux/fs.h | 5 +
include/uapi/linux/bpf.h | 12 +
include/uapi/linux/fuse.h | 41 +
kernel/bpf/Makefile | 4 +
kernel/bpf/bpf_fuse.c | 241 +
kernel/bpf/bpf_struct_ops.c | 6 +-
kernel/bpf/bpf_struct_ops_types.h | 4 +
kernel/bpf/btf.c | 1 +
kernel/bpf/helpers.c | 32 +-
kernel/bpf/verifier.c | 32 +
tools/include/uapi/linux/bpf.h | 12 +
tools/include/uapi/linux/fuse.h | 1135 +++++
.../testing/selftests/bpf/prog_tests/dynptr.c | 1 +
.../selftests/bpf/progs/dynptr_success.c | 21 +
.../selftests/filesystems/fuse/.gitignore | 2 +
.../selftests/filesystems/fuse/Makefile | 189 +
.../testing/selftests/filesystems/fuse/OWNERS | 2 +
.../selftests/filesystems/fuse/bpf_common.h | 51 +
.../selftests/filesystems/fuse/bpf_loader.c | 597 +++
.../testing/selftests/filesystems/fuse/fd.txt | 21 +
.../selftests/filesystems/fuse/fd_bpf.bpf.c | 397 ++
.../selftests/filesystems/fuse/fuse_daemon.c | 300 ++
.../selftests/filesystems/fuse/fuse_test.c | 2412 ++++++++++
.../filesystems/fuse/struct_op_test.bpf.c | 642 +++
.../selftests/filesystems/fuse/test.bpf.c | 996 ++++
.../filesystems/fuse/test_framework.h | 172 +
.../selftests/filesystems/fuse/test_fuse.h | 494 ++
44 files changed, 13755 insertions(+), 231 deletions(-)
create mode 100644 fs/fuse/backing.c
create mode 100644 fs/fuse/bpf_register.c
create mode 100644 include/linux/bpf_fuse.h
create mode 100644 kernel/bpf/bpf_fuse.c
create mode 100644 tools/include/uapi/linux/fuse.h
create mode 100644 tools/testing/selftests/filesystems/fuse/.gitignore
create mode 100644 tools/testing/selftests/filesystems/fuse/Makefile
create mode 100644 tools/testing/selftests/filesystems/fuse/OWNERS
create mode 100644 tools/testing/selftests/filesystems/fuse/bpf_common.h
create mode 100644 tools/testing/selftests/filesystems/fuse/bpf_loader.c
create mode 100644 tools/testing/selftests/filesystems/fuse/fd.txt
create mode 100644 tools/testing/selftests/filesystems/fuse/fd_bpf.bpf.c
create mode 100644 tools/testing/selftests/filesystems/fuse/fuse_daemon.c
create mode 100644 tools/testing/selftests/filesystems/fuse/fuse_test.c
create mode 100644 tools/testing/selftests/filesystems/fuse/struct_op_test.bpf.c
create mode 100644 tools/testing/selftests/filesystems/fuse/test.bpf.c
create mode 100644 tools/testing/selftests/filesystems/fuse/test_framework.h
create mode 100644 tools/testing/selftests/filesystems/fuse/test_fuse.h


base-commit: 49859de997c3115b85544bce6b6ceab60a7fabc4
--
2.40.0.634.g4ca3ef3211-goog