summaryrefslogtreecommitdiff
path: root/io_uring/io_uring.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2026-01-08 10:18:31 -0700
committerJens Axboe <axboe@kernel.dk>2026-02-06 07:29:19 -0700
commited82f35b926b2e505c14b7006473614b8f58b4f4 (patch)
treead7d9b985dc26d60349174c2590dc110a2c4f40b /io_uring/io_uring.c
parent9fd99788f3e5a129908c242bb29946077ca46611 (diff)
io_uring: allow registration of per-task restrictions
Currently io_uring supports restricting operations on a per-ring basis. To use those, the ring must be setup in a disabled state by setting IORING_SETUP_R_DISABLED. Then restrictions can be set for the ring, and the ring can then be enabled. This commit adds support for IORING_REGISTER_RESTRICTIONS with ring_fd == -1, like the other "blind" register opcodes which work on the task rather than a specific ring. This allows registration of the same kind of restrictions as can been done on a specific ring, but with the task itself. Once done, any ring created will inherit these restrictions. If a restriction filter is registered with a task, then it's inherited on fork for its children. Children may only further restrict operations, not extend them. Inheriting restrictions include both the classic IORING_REGISTER_RESTRICTIONS based restrictions, as well as the BPF filters that have been registered with the task via IORING_REGISTER_BPF_FILTER. Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'io_uring/io_uring.c')
-rw-r--r--io_uring/io_uring.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 049454278563..e43c5283b23a 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -2880,6 +2880,32 @@ int io_prepare_config(struct io_ctx_config *config)
return 0;
}
+void io_restriction_clone(struct io_restriction *dst, struct io_restriction *src)
+{
+ memcpy(&dst->register_op, &src->register_op, sizeof(dst->register_op));
+ memcpy(&dst->sqe_op, &src->sqe_op, sizeof(dst->sqe_op));
+ dst->sqe_flags_allowed = src->sqe_flags_allowed;
+ dst->sqe_flags_required = src->sqe_flags_required;
+ dst->op_registered = src->op_registered;
+ dst->reg_registered = src->reg_registered;
+
+ io_bpf_filter_clone(dst, src);
+}
+
+static void io_ctx_restriction_clone(struct io_ring_ctx *ctx,
+ struct io_restriction *src)
+{
+ struct io_restriction *dst = &ctx->restrictions;
+
+ io_restriction_clone(dst, src);
+ if (dst->bpf_filters)
+ WRITE_ONCE(ctx->bpf_filters, dst->bpf_filters->filters);
+ if (dst->op_registered)
+ ctx->op_restricted = 1;
+ if (dst->reg_registered)
+ ctx->reg_restricted = 1;
+}
+
static __cold int io_uring_create(struct io_ctx_config *config)
{
struct io_uring_params *p = &config->p;
@@ -2941,6 +2967,13 @@ static __cold int io_uring_create(struct io_ctx_config *config)
ctx->notify_method = TWA_SIGNAL;
/*
+ * If the current task has restrictions enabled, then copy them to
+ * our newly created ring and mark it as registered.
+ */
+ if (current->io_uring_restrict)
+ io_ctx_restriction_clone(ctx, current->io_uring_restrict);
+
+ /*
* This is just grabbed for accounting purposes. When a process exits,
* the mm is exited and dropped before the files, hence we need to hang
* on to this mm purely for the purposes of being able to unaccount