Skip to content

Commit d42eb05

Browse files
committed
io_uring: add support for BPF filtering for opcode restrictions
Add support for loading classic BPF programs with io_uring to provide fine-grained filtering of SQE operations. Unlike IORING_REGISTER_RESTRICTIONS which only allows bitmap-based allow/deny of opcodes, BPF filters can inspect request attributes and make dynamic decisions. The filter is registered via IORING_REGISTER_BPF_FILTER with a struct io_uring_bpf: struct io_uring_bpf_filter { __u32 opcode; /* io_uring opcode to filter */ __u32 flags; __u32 filter_len; /* number of BPF instructions */ __u32 resv; __u64 filter_ptr; /* pointer to BPF filter */ __u64 resv2[5]; }; enum { IO_URING_BPF_CMD_FILTER = 1, }; struct io_uring_bpf { __u16 cmd_type; /* IO_URING_BPF_* values */ __u16 cmd_flags; /* none so far */ __u32 resv; union { struct io_uring_bpf_filter filter; }; }; and the filters get supplied a struct io_uring_bpf_ctx: struct io_uring_bpf_ctx { __u64 user_data; __u8 opcode; __u8 sqe_flags; __u8 pdu_size; __u8 pad[5]; }; where it's possible to filter on opcode and sqe_flags, with pdu_size indicating how much extra data is being passed in beyond the pad field. This will used for specific finer grained filtering inside an opcode. An example of that for sockets is in one of the following patches. Anything the opcode supports can end up in this struct, populated by the opcode itself, and hence can be filtered for. Filters have the following semantics: - Return 1 to allow the request - Return 0 to deny the request with -EACCES - Multiple filters can be stacked per opcode. All filters must return 1 for the opcode to be allowed. - Filters are evaluated in registration order (most recent first) The implementation uses classic BPF (cBPF) rather than eBPF for as that's required for containers, and since they can be used by any user in the system. Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 0105b05 commit d42eb05

9 files changed

Lines changed: 447 additions & 0 deletions

File tree

include/linux/io_uring_types.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,18 @@ struct io_rings {
219219
struct io_uring_cqe cqes[] ____cacheline_aligned_in_smp;
220220
};
221221

222+
struct io_bpf_filter;
223+
struct io_bpf_filters {
224+
refcount_t refs; /* ref for ->bpf_filters */
225+
spinlock_t lock; /* protects ->bpf_filters modifications */
226+
struct io_bpf_filter __rcu **filters;
227+
struct rcu_head rcu_head;
228+
};
229+
222230
struct io_restriction {
223231
DECLARE_BITMAP(register_op, IORING_REGISTER_LAST);
224232
DECLARE_BITMAP(sqe_op, IORING_OP_LAST);
233+
struct io_bpf_filters *bpf_filters;
225234
u8 sqe_flags_allowed;
226235
u8 sqe_flags_required;
227236
/* IORING_OP_* restrictions exist */

include/uapi/linux/io_uring.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,9 @@ enum io_uring_register_op {
700700
/* auxiliary zcrx configuration, see enum zcrx_ctrl_op */
701701
IORING_REGISTER_ZCRX_CTRL = 36,
702702

703+
/* register bpf filtering programs */
704+
IORING_REGISTER_BPF_FILTER = 37,
705+
703706
/* this goes last */
704707
IORING_REGISTER_LAST,
705708

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR MIT */
2+
/*
3+
* Header file for the io_uring BPF filters.
4+
*/
5+
#ifndef LINUX_IO_URING_BPF_FILTER_H
6+
#define LINUX_IO_URING_BPF_FILTER_H
7+
8+
#include <linux/types.h>
9+
10+
/*
11+
* Struct passed to filters.
12+
*/
13+
struct io_uring_bpf_ctx {
14+
__u64 user_data;
15+
__u8 opcode;
16+
__u8 sqe_flags;
17+
__u8 pdu_size; /* size of aux data for filter */
18+
__u8 pad[5];
19+
};
20+
21+
enum {
22+
/*
23+
* If set, any currently unset opcode will have a deny filter attached
24+
*/
25+
IO_URING_BPF_FILTER_DENY_REST = 1,
26+
};
27+
28+
struct io_uring_bpf_filter {
29+
__u32 opcode; /* io_uring opcode to filter */
30+
__u32 flags;
31+
__u32 filter_len; /* number of BPF instructions */
32+
__u32 resv;
33+
__u64 filter_ptr; /* pointer to BPF filter */
34+
__u64 resv2[5];
35+
};
36+
37+
enum {
38+
IO_URING_BPF_CMD_FILTER = 1,
39+
};
40+
41+
struct io_uring_bpf {
42+
__u16 cmd_type; /* IO_URING_BPF_* values */
43+
__u16 cmd_flags; /* none so far */
44+
__u32 resv;
45+
union {
46+
struct io_uring_bpf_filter filter;
47+
};
48+
};
49+
50+
#endif

io_uring/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,8 @@ config IO_URING_ZCRX
99
depends on PAGE_POOL
1010
depends on INET
1111
depends on NET_RX_BUSY_POLL
12+
13+
config IO_URING_BPF
14+
def_bool y
15+
depends on BPF
16+
depends on NET

io_uring/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ obj-$(CONFIG_NET_RX_BUSY_POLL) += napi.o
2424
obj-$(CONFIG_NET) += net.o cmd_net.o
2525
obj-$(CONFIG_PROC_FS) += fdinfo.o
2626
obj-$(CONFIG_IO_URING_MOCK_FILE) += mock_file.o
27+
obj-$(CONFIG_IO_URING_BPF) += bpf_filter.o

0 commit comments

Comments
 (0)