
oss-sec mailing list archives
[CVE-2023-42752] integer overflow in Linux kernel leading to exploitable memory access
From: Kyle Zeng <zengyhkyle () gmail com>
Date: Mon, 18 Sep 2023 13:54:03 -0700
Hi there, I recently found an integer overflow in the Linux kernel, which leads to the kernel allocating `skb_shared_info` in the userspace, which is exploitable in systems without SMAP protection since `skb_shared_info` contains references to function pointers. I verified the existence of the vulnerability on both the main tree and v6.1.y, more versions may be affected (potentially all stable trees). [Root Cause] The root cause of the vulnerability is an insufficient check for integer overflow in `__alloc_skb`. As shown below: ``` struct sk_buff *__alloc_skb(unsigned int size, ...) { ...... data = kmalloc_reserve(&size, gfp_mask, node, &pfmemalloc); if (unlikely(!data)) goto nodata; ...... } ``` `size` is an `unsigned int` and it is potentially controlled by users. In `kmalloc_reserve`, it will round up the size by `PAGE_SIZE << get_order(size);` in `kmalloc_size_roundup`. Since `size` is `unsigned int`, the roundup logic will make it 0 if the original value is something huge such as 0xfffffed0. As a result, `data` will actually become `ZERO_SIZE_PTR`, which is 0x10 instead of 0. Since the check does not consider the case, the kernel will happily continue processing the `data` as if it is a valid kernel pointer. Later when the kernel tries to finalize the skb object in `__finalize_skb_around`, it has the code: `shinfo = skb_shinfo(skb);`, which is `skb->head+skb->end` where `skb->head` is 0x10 and `skb->end` is a large size such as 0xfffffed0. As a result, `shinfo` points to a userspace pointer. The kernel crashes at `memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));` in systems with SMAP enabled. The root cause of the bug was introduced in v6.2-rc1 in https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=12d6c1d3a2ad. But it gets backported to all stable trees, which may potentially introduce the bug to stable trees (that's why I could trigger the bug in v6.1.y). According to Vegard Nossum, this is the backported buggy patch: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=0dbc898f5917 [Impact] * The vulnerability is likely exploitable in systems without SMAP protection since `shinfo` has a function pointer member `destructor_arg`. Attackers can overwrite it to obtain code execution in kernel space. * The vulnerability can lead to local DoS from a user having access to user namespace * The vulnerability cannot be triggered remotely according to Eric Dumazet [Patch] I already contacted the linux kernel security team and assisted them in fixing the vulnerability. The patch consists of two commits: [1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=915d975b2ffa [2] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=c3b704d4a4a2 [Proof-of-Concept] A crashing poc is attached. Thanks, Kyle Zeng =================[Crashing Splash]========================== [ 4.367486] BUG: unable to handle page fault for address: 00000000fffffed0 [ 4.367792] #PF: supervisor write access in kernel mode [ 4.368029] #PF: error_code(0x0002) - not-present page [ 4.368260] PGD da2f067 P4D da2f067 PUD 0 [ 4.368447] Oops: 0002 [#1] PREEMPT SMP KASAN NOPTI [ 4.368668] CPU: 0 PID: 440 Comm: poc Tainted: G W 6.5.0+ #47 [ 4.368987] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 [ 4.369355] RIP: 0010:memset_orig+0x72/0xac [ 4.369546] Code: 47 28 48 89 47 30 48 89 47 38 48 8d 7f 40 75 d8 0f 1f 84 00 00 00 00 00 89 d1 83 e1 38 74 14 c1 e9 03 66 0f 1f 44 00 00 ff c9 <48> 89 07 48 8d 7f 08 75 f5 83 e2 07 74 0a ff ca 88 07 48 8d 7f 01 [ 4.370379] RSP: 0000:ffff88800e627a48 EFLAGS: 00010206 [ 4.370626] RAX: 0000000000000000 RBX: 0000000000000010 RCX: 0000000000000003 [ 4.370947] RDX: 0000000000000020 RSI: 0000000000000000 RDI: 00000000fffffed0 [ 4.371263] RBP: 00000000fffffec0 R08: ffff88800d8faad7 R09: 0000000000000000 [ 4.371580] R10: 00000000fffffed0 R11: ffffed1001b1f55b R12: 1ffff11001b1f557 [ 4.371896] R13: ffff88800d8faac0 R14: dffffc0000000000 R15: 1ffff11001b1f558 [ 4.372212] FS: 000000000207a3c0(0000) GS:ffff888036000000(0000) knlGS:0000000000000000 [ 4.372568] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 4.372825] CR2: 00000000fffffed0 CR3: 000000001115c005 CR4: 0000000000770ef0 [ 4.373147] PKRU: 55555554 [ 4.373278] Call Trace: [ 4.373392] <TASK> [ 4.373491] ? __die_body+0x67/0xb0 [ 4.373653] ? page_fault_oops+0x65a/0x7f0 [ 4.373839] ? exc_page_fault+0x76/0xe0 [ 4.374013] ? asm_exc_page_fault+0x22/0x30 [ 4.374202] ? memset_orig+0x72/0xac [ 4.374371] __build_skb_around+0x202/0x3c0 [ 4.374560] __alloc_skb+0x214/0x4e0 [ 4.374724] igmpv3_newpack+0xf8/0xfb0 [ 4.374895] add_grhead+0x6e/0x2b0 [ 4.375051] add_grec+0xfcf/0x12d0 [ 4.375216] igmp_ifc_timer_expire+0x72c/0xd20 [ 4.375412] ? igmp_gq_timer_expire+0x90/0x90 [ 4.375614] call_timer_fn+0xb9/0x1c0 [ 4.375781] ? igmp_gq_timer_expire+0x90/0x90 [ 4.375984] __run_timers+0x683/0x790 [ 4.376148] run_timer_softirq+0x46/0x80 [ 4.376330] __do_softirq+0x22e/0x51e [ 4.376497] __irq_exit_rcu+0x6f/0x120 [ 4.376673] sysvec_apic_timer_interrupt+0x43/0xb0 [ 4.376884] asm_sysvec_apic_timer_interrupt+0x16/0x20 [ 4.377119] RIP: 0033:0x401e38 [ 4.377260] Code: 53 07 00 89 45 bc 8b 05 3a 36 10 00 48 8d 55 b8 41 b8 08 00 00 00 48 89 d1 ba 23 00 00 00 be 00 00 00 00 89 c7 e8 c8 32 07 00 <eb> fe f3 0f 1e fa 55 48 89 e5 48 83 ec 70 48 89 7d 98 48 89 75 90 [ 4.378101] RSP: 002b:00007ffc1f22b390 EFLAGS: 00000207 [ 4.378370] RAX: 0000000000000000 RBX: 00007ffc1f22b5d8 RCX: 000000000047510e [ 4.378725] RDX: 0000000000000023 RSI: 0000000000000000 RDI: 0000000000000006 [ 4.379060] RBP: 00007ffc1f22b3e0 R08: 0000000000000008 R09: 0000000000000000 [ 4.379385] R10: 00007ffc1f22b398 R11: 0000000000000206 R12: 0000000000000001 [ 4.379717] R13: 00007ffc1f22b5c8 R14: 00000000004ff740 R15: 0000000000000002 [ 4.380048] </TASK> [ 4.380152] Modules linked in: [ 4.380296] CR2: 00000000fffffed0 [ 4.380451] ---[ end trace 0000000000000000 ]--- [ 4.380661] RIP: 0010:memset_orig+0x72/0xac [ 4.380851] Code: 47 28 48 89 47 30 48 89 47 38 48 8d 7f 40 75 d8 0f 1f 84 00 00 00 00 00 89 d1 83 e1 38 74 14 c1 e9 03 66 0f 1f 44 00 00 ff c9 <48> 89 07 48 8d 7f 08 75 f5 83 e2 07 74 0a ff ca 88 07 48 8d 7f 01 [ 4.381706] RSP: 0000:ffff88800e627a48 EFLAGS: 00010206 [ 4.381949] RAX: 0000000000000000 RBX: 0000000000000010 RCX: 0000000000000003 [ 4.382275] RDX: 0000000000000020 RSI: 0000000000000000 RDI: 00000000fffffed0 [ 4.382607] RBP: 00000000fffffec0 R08: ffff88800d8faad7 R09: 0000000000000000 [ 4.382926] R10: 00000000fffffed0 R11: ffffed1001b1f55b R12: 1ffff11001b1f557 [ 4.383271] R13: ffff88800d8faac0 R14: dffffc0000000000 R15: 1ffff11001b1f558 [ 4.383590] FS: 000000000207a3c0(0000) GS:ffff888036000000(0000) knlGS:0000000000000000 [ 4.384012] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 4.384298] CR2: 00000000fffffed0 CR3: 000000001115c005 CR4: 0000000000770ef0 [ 4.384635] PKRU: 55555554 [ 4.384763] Kernel panic - not syncing: Fatal exception in interrupt [ 4.385239] Kernel Offset: disabled [ 4.385413] Rebooting in 1000 seconds..
Attachment:
poc.c
Description:
Current thread:
- [CVE-2023-42752] integer overflow in Linux kernel leading to exploitable memory access Kyle Zeng (Sep 18)