Re: memory leak in prepare_creds

From: Pavel Begunkov
Date: Sun Dec 06 2020 - 08:35:30 EST


On 28/11/2020 08:00, Hillf Danton wrote:
> On Fri, 27 Nov 2020 19:47:15 -0800
>> syzbot has found a reproducer for the following issue on:
>>
>> HEAD commit: 99c710c4 Merge tag 'platform-drivers-x86-v5.10-2' of git:/..
>> git tree: upstream
>> console output: https://syzkaller.appspot.com/x/log.txt?x=12a77ddd500000
>> kernel config: https://syzkaller.appspot.com/x/.config?x=c7a27a77f20fbc95
>> dashboard link: https://syzkaller.appspot.com/bug?extid=71c4697e27c99fddcf17
>> compiler: gcc (GCC) 10.1.0-syz 20200507
>> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=12d6161d500000
>> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=16f15e65500000
>>
>> IMPORTANT: if you fix the issue, please add the following tag to the commit:
>> Reported-by: syzbot+71c4697e27c99fddcf17@xxxxxxxxxxxxxxxxxxxxxxxxx
>>
>> BUG: memory leak
>> unreferenced object 0xffff888101401300 (size 168):
>> comm "syz-executor355", pid 8461, jiffies 4294953658 (age 32.400s)
>> hex dump (first 32 bytes):
>> 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>> backtrace:
>> [<00000000caa0de2b>] prepare_creds+0x25/0x390 kernel/cred.c:258
>> [<000000001821b99d>] copy_creds+0x3a/0x230 kernel/cred.c:358
>> [<0000000022c32914>] copy_process+0x661/0x24d0 kernel/fork.c:1971
>> [<00000000d3adca2d>] kernel_clone+0xf3/0x670 kernel/fork.c:2456
>> [<00000000d11b7286>] __do_sys_clone+0x76/0xa0 kernel/fork.c:2573
>> [<000000008280baad>] do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
>> [<00000000685d8cf0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
>>
>> BUG: memory leak
>> unreferenced object 0xffff88810b0a6f20 (size 32):
>> comm "syz-executor355", pid 8461, jiffies 4294953658 (age 32.400s)
>> hex dump (first 32 bytes):
>> b0 6e 93 00 81 88 ff ff 00 00 00 00 00 00 00 00 .n..............
>> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
>> backtrace:
>> [<000000007d750ba1>] kmalloc include/linux/slab.h:557 [inline]
>> [<000000007d750ba1>] kzalloc include/linux/slab.h:664 [inline]
>> [<000000007d750ba1>] lsm_cred_alloc security/security.c:533 [inline]
>> [<000000007d750ba1>] security_prepare_creds+0xa5/0xd0 security/security.c:1632
>> [<00000000ba63fcc7>] prepare_creds+0x277/0x390 kernel/cred.c:285
>> [<000000001821b99d>] copy_creds+0x3a/0x230 kernel/cred.c:358
>> [<0000000022c32914>] copy_process+0x661/0x24d0 kernel/fork.c:1971
>> [<00000000d3adca2d>] kernel_clone+0xf3/0x670 kernel/fork.c:2456
>> [<00000000d11b7286>] __do_sys_clone+0x76/0xa0 kernel/fork.c:2573
>> [<000000008280baad>] do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
>> [<00000000685d8cf0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
>
> Fail to spot the cred leak.
>>
>> 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
>>
> Put file as part of the error handling after getting a new one.

Looks genuine to me, would you send a real patch?

>
> --- a/fs/io_uring.c
> +++ b/fs/io_uring.c
> @@ -9182,6 +9182,7 @@ static int io_uring_get_fd(struct io_rin
> {
> struct file *file;
> int ret;
> + int fd;
>
> #if defined(CONFIG_UNIX)
> ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP,
> @@ -9190,28 +9191,29 @@ static int io_uring_get_fd(struct io_rin
> return ret;
> #endif
>
> - ret = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
> + ret = fd = get_unused_fd_flags(O_RDWR | O_CLOEXEC);
> if (ret < 0)
> goto err;
>
> file = anon_inode_getfile("[io_uring]", &io_uring_fops, ctx,
> O_RDWR | O_CLOEXEC);
> if (IS_ERR(file)) {
> -err_fd:
> - put_unused_fd(ret);
> ret = PTR_ERR(file);
> + put_unused_fd(fd);
> goto err;
> }
>
> #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;
> + return 0;
> err:
> #if defined(CONFIG_UNIX)
> sock_release(ctx->ring_sock);
>

--
Pavel Begunkov