io_uring: Factor out a function to parse restrictions

Preparation for subsequent work on inherited restrictions.

Signed-off-by: Josh Triplett <josh@joshtriplett.org>
Reviewed-by: Pavel Begunkov <asml.silence@gmail.com>
Link: https://lore.kernel.org/r/9bac2b4d1b9b9ab41c55ea3816021be847f354df.1736932318.git.josh@joshtriplett.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Josh Triplett 2025-01-15 11:14:33 +02:00 committed by Jens Axboe
parent 19d340a298
commit 53745105ef

View File

@ -104,21 +104,13 @@ static int io_register_personality(struct io_ring_ctx *ctx)
return id; return id;
} }
static __cold int io_register_restrictions(struct io_ring_ctx *ctx, static __cold int io_parse_restrictions(void __user *arg, unsigned int nr_args,
void __user *arg, unsigned int nr_args) struct io_restriction *restrictions)
{ {
struct io_uring_restriction *res; struct io_uring_restriction *res;
size_t size; size_t size;
int i, ret; int i, ret;
/* Restrictions allowed only if rings started disabled */
if (!(ctx->flags & IORING_SETUP_R_DISABLED))
return -EBADFD;
/* We allow only a single restrictions registration */
if (ctx->restrictions.registered)
return -EBUSY;
if (!arg || nr_args > IORING_MAX_RESTRICTIONS) if (!arg || nr_args > IORING_MAX_RESTRICTIONS)
return -EINVAL; return -EINVAL;
@ -130,47 +122,57 @@ static __cold int io_register_restrictions(struct io_ring_ctx *ctx,
if (IS_ERR(res)) if (IS_ERR(res))
return PTR_ERR(res); return PTR_ERR(res);
ret = 0; ret = -EINVAL;
for (i = 0; i < nr_args; i++) { for (i = 0; i < nr_args; i++) {
switch (res[i].opcode) { switch (res[i].opcode) {
case IORING_RESTRICTION_REGISTER_OP: case IORING_RESTRICTION_REGISTER_OP:
if (res[i].register_op >= IORING_REGISTER_LAST) { if (res[i].register_op >= IORING_REGISTER_LAST)
ret = -EINVAL; goto err;
goto out; __set_bit(res[i].register_op, restrictions->register_op);
}
__set_bit(res[i].register_op,
ctx->restrictions.register_op);
break; break;
case IORING_RESTRICTION_SQE_OP: case IORING_RESTRICTION_SQE_OP:
if (res[i].sqe_op >= IORING_OP_LAST) { if (res[i].sqe_op >= IORING_OP_LAST)
ret = -EINVAL; goto err;
goto out; __set_bit(res[i].sqe_op, restrictions->sqe_op);
}
__set_bit(res[i].sqe_op, ctx->restrictions.sqe_op);
break; break;
case IORING_RESTRICTION_SQE_FLAGS_ALLOWED: case IORING_RESTRICTION_SQE_FLAGS_ALLOWED:
ctx->restrictions.sqe_flags_allowed = res[i].sqe_flags; restrictions->sqe_flags_allowed = res[i].sqe_flags;
break; break;
case IORING_RESTRICTION_SQE_FLAGS_REQUIRED: case IORING_RESTRICTION_SQE_FLAGS_REQUIRED:
ctx->restrictions.sqe_flags_required = res[i].sqe_flags; restrictions->sqe_flags_required = res[i].sqe_flags;
break; break;
default: default:
ret = -EINVAL; goto err;
goto out;
} }
} }
out: ret = 0;
err:
kfree(res);
return ret;
}
static __cold int io_register_restrictions(struct io_ring_ctx *ctx,
void __user *arg, unsigned int nr_args)
{
int ret;
/* Restrictions allowed only if rings started disabled */
if (!(ctx->flags & IORING_SETUP_R_DISABLED))
return -EBADFD;
/* We allow only a single restrictions registration */
if (ctx->restrictions.registered)
return -EBUSY;
ret = io_parse_restrictions(arg, nr_args, &ctx->restrictions);
/* Reset all restrictions if an error happened */ /* Reset all restrictions if an error happened */
if (ret != 0) if (ret != 0)
memset(&ctx->restrictions, 0, sizeof(ctx->restrictions)); memset(&ctx->restrictions, 0, sizeof(ctx->restrictions));
else else
ctx->restrictions.registered = true; ctx->restrictions.registered = true;
kfree(res);
return ret; return ret;
} }