diff options
| author | Jens Axboe <axboe@kernel.dk> | 2026-01-16 14:50:05 -0700 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2026-01-27 11:10:46 -0700 |
| commit | cff1c26b4223820431129696b45525e5928e6409 (patch) | |
| tree | ea5c121a8b097955159bb90412c464fb38bd0364 | |
| parent | d42eb05e60fea31de49897d63a1d73f933303bd4 (diff) | |
io_uring/net: allow filtering on IORING_OP_SOCKET data
Example population method for the BPF based opcode filtering. This
exposes the socket family, type, and protocol to a registered BPF
filter. This in turn enables the filter to make decisions based on
what was passed in to the IORING_OP_SOCKET request type.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
| -rw-r--r-- | include/uapi/linux/io_uring/bpf_filter.h | 7 | ||||
| -rw-r--r-- | io_uring/bpf_filter.c | 11 | ||||
| -rw-r--r-- | io_uring/net.c | 9 | ||||
| -rw-r--r-- | io_uring/net.h | 6 |
4 files changed, 33 insertions, 0 deletions
diff --git a/include/uapi/linux/io_uring/bpf_filter.h b/include/uapi/linux/io_uring/bpf_filter.h index 2d4d0e5743e4..4dbc89bbbf10 100644 --- a/include/uapi/linux/io_uring/bpf_filter.h +++ b/include/uapi/linux/io_uring/bpf_filter.h @@ -16,6 +16,13 @@ struct io_uring_bpf_ctx { __u8 sqe_flags; __u8 pdu_size; /* size of aux data for filter */ __u8 pad[5]; + union { + struct { + __u32 family; + __u32 type; + __u32 protocol; + } socket; + }; }; enum { diff --git a/io_uring/bpf_filter.c b/io_uring/bpf_filter.c index 5207226d72ea..889fa915fa54 100644 --- a/io_uring/bpf_filter.c +++ b/io_uring/bpf_filter.c @@ -30,6 +30,17 @@ static void io_uring_populate_bpf_ctx(struct io_uring_bpf_ctx *bctx, /* clear residual, anything from pdu_size and below */ memset((void *) bctx + offsetof(struct io_uring_bpf_ctx, pdu_size), 0, sizeof(*bctx) - offsetof(struct io_uring_bpf_ctx, pdu_size)); + + /* + * Opcodes can provide a handler fo populating more data into bctx, + * for filters to use. + */ + switch (req->opcode) { + case IORING_OP_SOCKET: + bctx->pdu_size = sizeof(bctx->socket); + io_socket_bpf_populate(bctx, req); + break; + } } /* diff --git a/io_uring/net.c b/io_uring/net.c index 519ea055b761..4fcba36bd0bb 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -1699,6 +1699,15 @@ retry: return IOU_COMPLETE; } +void io_socket_bpf_populate(struct io_uring_bpf_ctx *bctx, struct io_kiocb *req) +{ + struct io_socket *sock = io_kiocb_to_cmd(req, struct io_socket); + + bctx->socket.family = sock->domain; + bctx->socket.type = sock->type; + bctx->socket.protocol = sock->protocol; +} + int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { struct io_socket *sock = io_kiocb_to_cmd(req, struct io_socket); diff --git a/io_uring/net.h b/io_uring/net.h index 43e5ce5416b7..a862960a3bb9 100644 --- a/io_uring/net.h +++ b/io_uring/net.h @@ -3,6 +3,7 @@ #include <linux/net.h> #include <linux/uio.h> #include <linux/io_uring_types.h> +#include <uapi/linux/io_uring/bpf_filter.h> struct io_async_msghdr { #if defined(CONFIG_NET) @@ -44,6 +45,7 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags); int io_socket_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); int io_socket(struct io_kiocb *req, unsigned int issue_flags); +void io_socket_bpf_populate(struct io_uring_bpf_ctx *bctx, struct io_kiocb *req); int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe); int io_connect(struct io_kiocb *req, unsigned int issue_flags); @@ -64,4 +66,8 @@ void io_netmsg_cache_free(const void *entry); static inline void io_netmsg_cache_free(const void *entry) { } +static inline void io_socket_bpf_populate(struct io_uring_bpf_ctx *bctx, + struct io_kiocb *req) +{ +} #endif |
