2022-11-29 08:46:09

by syzbot

[permalink] [raw]
Subject: [syzbot] WARNING: kmalloc bug in btrfs_ioctl_send

Hello,

syzbot found the following issue on:

HEAD commit: 6d464646530f Merge branch 'for-next/core' into for-kernelci
git tree: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
console output: https://syzkaller.appspot.com/x/log.txt?x=176a733d880000
kernel config: https://syzkaller.appspot.com/x/.config?x=54b747d981acc7b7
dashboard link: https://syzkaller.appspot.com/bug?extid=4376a9a073770c173269
compiler: Debian clang version 13.0.1-++20220126092033+75e33f71c2da-1~exp1~20220126212112.63, GNU ld (GNU Binutils for Debian) 2.35.2
userspace arch: arm64
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=134c3d03880000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=13237ca1880000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/d75f5f77b3a3/disk-6d464646.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/9382f86e4d95/vmlinux-6d464646.xz
kernel image: https://storage.googleapis.com/syzbot-assets/cf2b5f0d51dd/Image-6d464646.gz.xz
mounted in repro: https://storage.googleapis.com/syzbot-assets/aa0da055eccb/mount_0.gz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: [email protected]

BTRFS info (device loop0): using free space tree
BTRFS info (device loop0): enabling ssd optimizations
BTRFS info (device loop0): checking UUID tree
------------[ cut here ]------------
WARNING: CPU: 1 PID: 3072 at mm/util.c:596 kvmalloc_node+0x19c/0x1a4
Modules linked in:
CPU: 1 PID: 3072 Comm: syz-executor189 Not tainted 6.1.0-rc6-syzkaller-32662-g6d464646530f #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/30/2022
pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : kvmalloc_node+0x19c/0x1a4
lr : kvmalloc_node+0x198/0x1a4 mm/util.c:596
sp : ffff800012f13c40
x29: ffff800012f13c50 x28: ffff0000cbb01000 x27: 0000000000000000
x26: 0000000000000000 x25: ffff0000c97a8a10 x24: ffff0000c6fa6400
x23: 0000000000000000 x22: ffff8000091f72d8 x21: 000caf0ca5eccda0
x20: 00000000ffffffff x19: 0000000000000dc0 x18: 0000000000000010
x17: ffff80000c0f0b68 x16: ffff80000dbe6158 x15: ffff0000c43a1a40
x14: 0000000000000000 x13: 00000000ffffffff x12: ffff0000c43a1a40
x11: ff808000084361e8 x10: 0000000000000000 x9 : ffff8000084361e8
x8 : ffff0000c43a1a40 x7 : ffff800008578874 x6 : 0000000000000000
x5 : 00000000ffffffff x4 : 0000000000012dc0 x3 : 0010000000000000
x2 : 000caf0ca5eccda0 x1 : 0000000000000000 x0 : 0000000000000000
Call trace:
kvmalloc_node+0x19c/0x1a4
kvmalloc include/linux/slab.h:706 [inline]
kvmalloc_array include/linux/slab.h:724 [inline]
kvcalloc include/linux/slab.h:729 [inline]
btrfs_ioctl_send+0x64c/0xed0 fs/btrfs/send.c:7915
_btrfs_ioctl_send+0x188/0x218 fs/btrfs/ioctl.c:5233
btrfs_ioctl+0x5c0/0xa64
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:870 [inline]
__se_sys_ioctl fs/ioctl.c:856 [inline]
__arm64_sys_ioctl+0xd0/0x140 fs/ioctl.c:856
__invoke_syscall arch/arm64/kernel/syscall.c:38 [inline]
invoke_syscall arch/arm64/kernel/syscall.c:52 [inline]
el0_svc_common+0x138/0x220 arch/arm64/kernel/syscall.c:142
do_el0_svc+0x48/0x164 arch/arm64/kernel/syscall.c:206
el0_svc+0x58/0x150 arch/arm64/kernel/entry-common.c:637
el0t_64_sync_handler+0x84/0xf0 arch/arm64/kernel/entry-common.c:655
el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:584
irq event stamp: 82706
hardirqs last enabled at (82705): [<ffff80000844b028>] mod_lruvec_page_state include/linux/vmstat.h:563 [inline]
hardirqs last enabled at (82705): [<ffff80000844b028>] __kmalloc_large_node+0x108/0x188 mm/slab_common.c:1099
hardirqs last disabled at (82706): [<ffff80000c07d8b4>] el1_dbg+0x24/0x80 arch/arm64/kernel/entry-common.c:405
softirqs last enabled at (82616): [<ffff80000801c38c>] local_bh_enable+0x10/0x34 include/linux/bottom_half.h:32
softirqs last disabled at (82614): [<ffff80000801c358>] local_bh_disable+0x10/0x34 include/linux/bottom_half.h:19
---[ end trace 0000000000000000 ]---


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at [email protected].

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
syzbot can test patches for this issue, for details see:
https://goo.gl/tpsmEJ#testing-patches


2022-11-29 16:01:35

by David Sterba

[permalink] [raw]
Subject: Re: [syzbot] WARNING: kmalloc bug in btrfs_ioctl_send

On Tue, Nov 29, 2022 at 12:21:41AM -0800, syzbot wrote:
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: 6d464646530f Merge branch 'for-next/core' into for-kernelci
> git tree: git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-kernelci
> console output: https://syzkaller.appspot.com/x/log.txt?x=176a733d880000
> kernel config: https://syzkaller.appspot.com/x/.config?x=54b747d981acc7b7
> dashboard link: https://syzkaller.appspot.com/bug?extid=4376a9a073770c173269
> compiler: Debian clang version 13.0.1-++20220126092033+75e33f71c2da-1~exp1~20220126212112.63, GNU ld (GNU Binutils for Debian) 2.35.2
> userspace arch: arm64
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=134c3d03880000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=13237ca1880000
>
> Downloadable assets:
> disk image: https://storage.googleapis.com/syzbot-assets/d75f5f77b3a3/disk-6d464646.raw.xz
> vmlinux: https://storage.googleapis.com/syzbot-assets/9382f86e4d95/vmlinux-6d464646.xz
> kernel image: https://storage.googleapis.com/syzbot-assets/cf2b5f0d51dd/Image-6d464646.gz.xz
> mounted in repro: https://storage.googleapis.com/syzbot-assets/aa0da055eccb/mount_0.gz
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: [email protected]
>
> BTRFS info (device loop0): using free space tree
> BTRFS info (device loop0): enabling ssd optimizations
> BTRFS info (device loop0): checking UUID tree
> ------------[ cut here ]------------
> WARNING: CPU: 1 PID: 3072 at mm/util.c:596 kvmalloc_node+0x19c/0x1a4

594 /* Don't even allow crazy sizes */
595 if (unlikely(size > INT_MAX)) {
596 WARN_ON_ONCE(!(flags & __GFP_NOWARN));
597 return NULL;
598 }

> Modules linked in:
> CPU: 1 PID: 3072 Comm: syz-executor189 Not tainted 6.1.0-rc6-syzkaller-32662-g6d464646530f #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/30/2022
> pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> pc : kvmalloc_node+0x19c/0x1a4
> lr : kvmalloc_node+0x198/0x1a4 mm/util.c:596
> sp : ffff800012f13c40
> x29: ffff800012f13c50 x28: ffff0000cbb01000 x27: 0000000000000000
> x26: 0000000000000000 x25: ffff0000c97a8a10 x24: ffff0000c6fa6400
> x23: 0000000000000000 x22: ffff8000091f72d8 x21: 000caf0ca5eccda0
> x20: 00000000ffffffff x19: 0000000000000dc0 x18: 0000000000000010
> x17: ffff80000c0f0b68 x16: ffff80000dbe6158 x15: ffff0000c43a1a40
> x14: 0000000000000000 x13: 00000000ffffffff x12: ffff0000c43a1a40
> x11: ff808000084361e8 x10: 0000000000000000 x9 : ffff8000084361e8
> x8 : ffff0000c43a1a40 x7 : ffff800008578874 x6 : 0000000000000000
> x5 : 00000000ffffffff x4 : 0000000000012dc0 x3 : 0010000000000000
> x2 : 000caf0ca5eccda0 x1 : 0000000000000000 x0 : 0000000000000000
> Call trace:
> kvmalloc_node+0x19c/0x1a4
> kvmalloc include/linux/slab.h:706 [inline]
> kvmalloc_array include/linux/slab.h:724 [inline]
> kvcalloc include/linux/slab.h:729 [inline]
> btrfs_ioctl_send+0x64c/0xed0 fs/btrfs/send.c:7915

7915 sctx->clone_roots = kvcalloc(sizeof(*sctx->clone_roots),
7916 arg->clone_sources_count + 1,
7917 GFP_KERNEL)

So we get some insane amount of clone_sources_count

> _btrfs_ioctl_send+0x188/0x218 fs/btrfs/ioctl.c:5233
> btrfs_ioctl+0x5c0/0xa64
> vfs_ioctl fs/ioctl.c:51 [inline]

2023-01-22 11:47:00

by syzbot

[permalink] [raw]
Subject: Re: [syzbot] [btrfs?] WARNING: kmalloc bug in btrfs_ioctl_send

syzbot has bisected this issue to:

commit 7661809d493b426e979f39ab512e3adf41fbcc69
Author: Linus Torvalds <[email protected]>
Date: Wed Jul 14 16:45:49 2021 +0000

mm: don't allow oversized kvmalloc() calls

bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=13f2c851480000
start commit: f9ff5644bcc0 Merge tag 'hsi-for-6.2' of git://git.kernel.o..
git tree: upstream
final oops: https://syzkaller.appspot.com/x/report.txt?x=100ac851480000
console output: https://syzkaller.appspot.com/x/log.txt?x=17f2c851480000
kernel config: https://syzkaller.appspot.com/x/.config?x=827916bd156c2ec6
dashboard link: https://syzkaller.appspot.com/bug?extid=4376a9a073770c173269
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1775aed7880000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=11cbcbd0480000

Reported-by: [email protected]
Fixes: 7661809d493b ("mm: don't allow oversized kvmalloc() calls")

For information about bisection process see: https://goo.gl/tpsmEJ#bisection

2023-01-22 19:53:30

by Linus Torvalds

[permalink] [raw]
Subject: Re: [syzbot] [btrfs?] WARNING: kmalloc bug in btrfs_ioctl_send

On Sun, Jan 22, 2023 at 3:14 AM syzbot
<[email protected]> wrote:
>
> syzbot has bisected this issue to:
>
> commit 7661809d493b426e979f39ab512e3adf41fbcc69
> Author: Linus Torvalds <[email protected]>
> Date: Wed Jul 14 16:45:49 2021 +0000
>
> mm: don't allow oversized kvmalloc() calls

Heh. I assume this is the

sctx->clone_roots = kvcalloc(sizeof(*sctx->clone_roots),
arg->clone_sources_count + 1,
GFP_KERNEL);

in btrfs_ioctl_send(), where the 'clone_sources_count' thing is
basically just an argument to the btrfs ioctl, and user space can set
it to anything it damn well likes.

So that warning is very much correct, and the problem is that the code
doesn't do any realsanity checking at all on the ioctl arguments, and
basically allows the code to exhaust all memory.

Ok, there's a sanity check in the form of an overflow check:

/*
* Check that we don't overflow at later allocations, we request
* clone_sources_count + 1 items, and compare to unsigned long inside
* access_ok.
*/
if (arg->clone_sources_count >
ULONG_MAX / sizeof(struct clone_root) - 1) {
ret = -EINVAL;
goto out;
}

but ULONG_MAX is a *lot* of memory that the btrfs code is happy to try
to allocate.

This ioctl does seem to be protected by a

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

so at least it wasn't some kind of "random user can use up all memory".

I suspect the simplest way to make syzbot happy is to change the

if (arg->clone_sources_count >
ULONG_MAX / sizeof(struct clone_root) - 1) {

test to use INT_MAX instead of ULONG_MAX, which will then match the
vmalloc sanity check and avoid the warning.

But maybe an even smaller value might be more domain-appropriate here?

Linus

2023-01-24 17:52:52

by David Sterba

[permalink] [raw]
Subject: Re: [syzbot] [btrfs?] WARNING: kmalloc bug in btrfs_ioctl_send

On Sun, Jan 22, 2023 at 11:53:08AM -0800, Linus Torvalds wrote:
> On Sun, Jan 22, 2023 at 3:14 AM syzbot
> <[email protected]> wrote:
> >
> > syzbot has bisected this issue to:
> >
> > commit 7661809d493b426e979f39ab512e3adf41fbcc69
> > Author: Linus Torvalds <[email protected]>
> > Date: Wed Jul 14 16:45:49 2021 +0000
> >
> > mm: don't allow oversized kvmalloc() calls
>
> Heh. I assume this is the
>
> sctx->clone_roots = kvcalloc(sizeof(*sctx->clone_roots),
> arg->clone_sources_count + 1,
> GFP_KERNEL);
>
> in btrfs_ioctl_send(), where the 'clone_sources_count' thing is
> basically just an argument to the btrfs ioctl, and user space can set
> it to anything it damn well likes.
>
> So that warning is very much correct, and the problem is that the code
> doesn't do any realsanity checking at all on the ioctl arguments, and
> basically allows the code to exhaust all memory.
>
> Ok, there's a sanity check in the form of an overflow check:
>
> /*
> * Check that we don't overflow at later allocations, we request
> * clone_sources_count + 1 items, and compare to unsigned long inside
> * access_ok.
> */
> if (arg->clone_sources_count >
> ULONG_MAX / sizeof(struct clone_root) - 1) {
> ret = -EINVAL;
> goto out;
> }
>
> but ULONG_MAX is a *lot* of memory that the btrfs code is happy to try
> to allocate.
>
> This ioctl does seem to be protected by a
>
> if (!capable(CAP_SYS_ADMIN))
> return -EPERM;
>
> so at least it wasn't some kind of "random user can use up all memory".
>
> I suspect the simplest way to make syzbot happy is to change the
>
> if (arg->clone_sources_count >
> ULONG_MAX / sizeof(struct clone_root) - 1) {
>
> test to use INT_MAX instead of ULONG_MAX, which will then match the
> vmalloc sanity check and avoid the warning.
>
> But maybe an even smaller value might be more domain-appropriate here?

Real world number for clone_sources_count would be low, in tens or
hundreds at most. Size of struct clone_root is 40 bytes, and 1M array
can hold about 26K items, which is enough for some realistic stress
testing. I'll set the limit for allocated memory to 8M which should be
generous (about 200K array items) and future proof in case new members
need to be added to clone_root.