diff options
| author | Jens Axboe <axboe@kernel.dk> | 2026-01-08 10:18:31 -0700 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2026-02-06 07:29:19 -0700 |
| commit | ed82f35b926b2e505c14b7006473614b8f58b4f4 (patch) | |
| tree | ad7d9b985dc26d60349174c2590dc110a2c4f40b /io_uring/io_uring.c | |
| parent | 9fd99788f3e5a129908c242bb29946077ca46611 (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.c | 33 |
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 |
