On 5/4/20 7:53 AM, Xiaoguang Wang wrote: > If copy_to_user() in io_uring_setup() failed, we'll leak many kernel > resources, which could be reproduced by using mprotect to set params > to PROT_READ. To fix this issue, refactor io_uring_create() a bit to > let it return 'struct io_ring_ctx *', then when copy_to_user() failed, > we can free kernel resource properly. Might be simpler to just pass in the __user pointer for the copy, ala the below. Totally untested... diff --git a/fs/io_uring.c b/fs/io_uring.c index 6d52ff98279d..70361f588c5b 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -7760,7 +7760,8 @@ static int io_uring_get_fd(struct io_ring_ctx *ctx) return ret; } -static int io_uring_create(unsigned entries, struct io_uring_params *p) +static int io_uring_create(unsigned entries, struct io_uring_params *p, + struct io_uring_params __user *params) { struct user_struct *user = NULL; struct io_ring_ctx *ctx; @@ -7863,6 +7864,12 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p) p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP | IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS | IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL; + + if (copy_to_user(params, p, sizeof(*p))) { + ret = -EFAULT; + goto err; + } + trace_io_uring_create(ret, ctx, p->sq_entries, p->cq_entries, p->flags); return ret; err: @@ -7878,7 +7885,6 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p) static long io_uring_setup(u32 entries, struct io_uring_params __user *params) { struct io_uring_params p; - long ret; int i; if (copy_from_user(&p, params, sizeof(p))) @@ -7893,14 +7899,7 @@ static long io_uring_setup(u32 entries, struct io_uring_params __user *params) IORING_SETUP_CLAMP | IORING_SETUP_ATTACH_WQ)) return -EINVAL; - ret = io_uring_create(entries, &p); - if (ret < 0) - return ret; - - if (copy_to_user(params, &p, sizeof(p))) - return -EFAULT; - - return ret; + return io_uring_create(entries, &p, params); } SYSCALL_DEFINE2(io_uring_setup, u32, entries, -- Jens Axboe