io_uring: fix file leak on error path of io ctx creation
authorHillf Danton <hdanton@sina.com>
Tue, 8 Dec 2020 15:54:26 +0000 (08:54 -0700)
committerJens Axboe <axboe@kernel.dk>
Tue, 8 Dec 2020 15:54:26 +0000 (08:54 -0700)
Put file as part of error handling when setting up io ctx to fix
memory leaks like the following one.

   BUG: memory leak
   unreferenced object 0xffff888101ea2200 (size 256):
     comm "syz-executor355", pid 8470, jiffies 4294953658 (age 32.400s)
     hex dump (first 32 bytes):
       00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
       20 59 03 01 81 88 ff ff 80 87 a8 10 81 88 ff ff   Y..............
     backtrace:
       [<000000002e0a7c5f>] kmem_cache_zalloc include/linux/slab.h:654 [inline]
       [<000000002e0a7c5f>] __alloc_file+0x1f/0x130 fs/file_table.c:101
       [<000000001a55b73a>] alloc_empty_file+0x69/0x120 fs/file_table.c:151
       [<00000000fb22349e>] alloc_file+0x33/0x1b0 fs/file_table.c:193
       [<000000006e1465bb>] alloc_file_pseudo+0xb2/0x140 fs/file_table.c:233
       [<000000007118092a>] anon_inode_getfile fs/anon_inodes.c:91 [inline]
       [<000000007118092a>] anon_inode_getfile+0xaa/0x120 fs/anon_inodes.c:74
       [<000000002ae99012>] io_uring_get_fd fs/io_uring.c:9198 [inline]
       [<000000002ae99012>] io_uring_create fs/io_uring.c:9377 [inline]
       [<000000002ae99012>] io_uring_setup+0x1125/0x1630 fs/io_uring.c:9411
       [<000000008280baad>] do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
       [<00000000685d8cf0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9

Reported-by: syzbot+71c4697e27c99fddcf17@syzkaller.appspotmail.com
Fixes: 0f2122045b94 ("io_uring: don't rely on weak ->files references")
Cc: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Hillf Danton <hdanton@sina.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c

index 908817c..86dac2b 100644 (file)
@@ -9183,6 +9183,7 @@ static int io_uring_get_fd(struct io_ring_ctx *ctx)
 {
        struct file *file;
        int ret;
+       int fd;
 
 #if defined(CONFIG_UNIX)
        ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP,
@@ -9194,12 +9195,12 @@ static int io_uring_get_fd(struct io_ring_ctx *ctx)
        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,
                                        O_RDWR | O_CLOEXEC);
        if (IS_ERR(file)) {
-err_fd:
-               put_unused_fd(ret);
+               put_unused_fd(fd);
                ret = PTR_ERR(file);
                goto err;
        }
@@ -9207,12 +9208,14 @@ err_fd:
 #if defined(CONFIG_UNIX)
        ctx->ring_sock->file = file;
 #endif
-       if (unlikely(io_uring_add_task_file(ctx, file))) {
-               file = ERR_PTR(-ENOMEM);
-               goto err_fd;
+       ret = io_uring_add_task_file(ctx, file);
+       if (ret) {
+               fput(file);
+               put_unused_fd(fd);
+               goto err;
        }
-       fd_install(ret, file);
-       return ret;
+       fd_install(fd, file);
+       return fd;
 err:
 #if defined(CONFIG_UNIX)
        sock_release(ctx->ring_sock);