Commit 9faadcc8 authored by Pavel Begunkov's avatar Pavel Begunkov Committed by Jens Axboe

io_uring: fix double io_uring free

Once we created a file for current context during setup, we should not
call io_ring_ctx_wait_and_kill() directly as it'll be done by fput(file)

Cc: stable@vger.kernel.org # 5.10
Reported-by: syzbot+c9937dfb2303a5f18640@syzkaller.appspotmail.com
Signed-off-by: default avatarPavel Begunkov <asml.silence@gmail.com>
[axboe: fix unused 'ret' for !CONFIG_UNIX]
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent a528b04e
...@@ -9379,55 +9379,52 @@ static int io_allocate_scq_urings(struct io_ring_ctx *ctx, ...@@ -9379,55 +9379,52 @@ static int io_allocate_scq_urings(struct io_ring_ctx *ctx,
return 0; return 0;
} }
static int io_uring_install_fd(struct io_ring_ctx *ctx, struct file *file)
{
int ret, fd;
fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
if (fd < 0)
return fd;
ret = io_uring_add_task_file(ctx, file);
if (ret) {
put_unused_fd(fd);
return ret;
}
fd_install(fd, file);
return fd;
}
/* /*
* Allocate an anonymous fd, this is what constitutes the application * Allocate an anonymous fd, this is what constitutes the application
* visible backing of an io_uring instance. The application mmaps this * visible backing of an io_uring instance. The application mmaps this
* fd to gain access to the SQ/CQ ring details. If UNIX sockets are enabled, * fd to gain access to the SQ/CQ ring details. If UNIX sockets are enabled,
* we have to tie this fd to a socket for file garbage collection purposes. * we have to tie this fd to a socket for file garbage collection purposes.
*/ */
static int io_uring_get_fd(struct io_ring_ctx *ctx) static struct file *io_uring_get_file(struct io_ring_ctx *ctx)
{ {
struct file *file; struct file *file;
#if defined(CONFIG_UNIX)
int ret; int ret;
int fd;
#if defined(CONFIG_UNIX)
ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP, ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP,
&ctx->ring_sock); &ctx->ring_sock);
if (ret) if (ret)
return ret; return ERR_PTR(ret);
#endif #endif
ret = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
if (ret < 0)
goto err;
fd = ret;
file = anon_inode_getfile("[io_uring]", &io_uring_fops, ctx, file = anon_inode_getfile("[io_uring]", &io_uring_fops, ctx,
O_RDWR | O_CLOEXEC); O_RDWR | O_CLOEXEC);
if (IS_ERR(file)) {
put_unused_fd(fd);
ret = PTR_ERR(file);
goto err;
}
#if defined(CONFIG_UNIX) #if defined(CONFIG_UNIX)
ctx->ring_sock->file = file; if (IS_ERR(file)) {
#endif sock_release(ctx->ring_sock);
ret = io_uring_add_task_file(ctx, file); ctx->ring_sock = NULL;
if (ret) { } else {
fput(file); ctx->ring_sock->file = file;
put_unused_fd(fd);
goto err;
} }
fd_install(fd, file);
return fd;
err:
#if defined(CONFIG_UNIX)
sock_release(ctx->ring_sock);
ctx->ring_sock = NULL;
#endif #endif
return ret; return file;
} }
static int io_uring_create(unsigned entries, struct io_uring_params *p, static int io_uring_create(unsigned entries, struct io_uring_params *p,
...@@ -9435,6 +9432,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p, ...@@ -9435,6 +9432,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
{ {
struct user_struct *user = NULL; struct user_struct *user = NULL;
struct io_ring_ctx *ctx; struct io_ring_ctx *ctx;
struct file *file;
bool limit_mem; bool limit_mem;
int ret; int ret;
...@@ -9582,13 +9580,22 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p, ...@@ -9582,13 +9580,22 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
goto err; goto err;
} }
file = io_uring_get_file(ctx);
if (IS_ERR(file)) {
ret = PTR_ERR(file);
goto err;
}
/* /*
* Install ring fd as the very last thing, so we don't risk someone * Install ring fd as the very last thing, so we don't risk someone
* having closed it before we finish setup * having closed it before we finish setup
*/ */
ret = io_uring_get_fd(ctx); ret = io_uring_install_fd(ctx, file);
if (ret < 0) if (ret < 0) {
goto err; /* fput will clean it up */
fput(file);
return ret;
}
trace_io_uring_create(ret, ctx, p->sq_entries, p->cq_entries, p->flags); trace_io_uring_create(ret, ctx, p->sq_entries, p->cq_entries, p->flags);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment