CVE-2021-47118: pid: take a reference when initializing `cad_pid`
In the Linux kernel, the following vulnerability has been resolved:
pid: take a reference when initializing cadpid
During boot, kernelinitfreeable() initializes cadpid to the init task's struct pid. Later on, we may change cadpid via a sysctl, and when this happens procdocadpid() will increment the refcount on the new pid via getpid(), and will decrement the refcount on the old pid via putpid(). As we never called getpid() when we initialized cadpid, we decrement a reference we never incremented, can therefore free the init task's struct pid early. As there can be dangling references to the struct pid, we can later encounter a use-after-free (e.g. when delivering signals).
This was spotted when fuzzing v5.13-rc3 with Syzkaller, but seems to have been around since the conversion of cadpid to struct pid in commit 9ec52099e4b8 ("[PATCH] replace cadpid by a struct pid") from the pre-KASAN stone age of v2.6.19.
Fix this by getting a reference to the init task's struct pid when we assign it to cadpid.
Full KASAN splat below.
================================================================== BUG: KASAN: use-after-free in nsofpid include/linux/pid.h:153 [inline] BUG: KASAN: use-after-free in taskactivepidns+0xc0/0xc8 kernel/pid.c:509 Read of size 4 at addr ffff23794dda0004 by task syz-executor.0/273
CPU: 1 PID: 273 Comm: syz-executor.0 Not tainted 5.12.0-00001-g9aef892b2d15 #1 Hardware name: linux,dummy-virt (DT) Call trace: nsofpid include/linux/pid.h:153 [inline] taskactivepidns+0xc0/0xc8 kernel/pid.c:509 donotifyparent+0x308/0xe60 kernel/signal.c:1950 exitnotify kernel/exit.c:682 [inline] doexit+0x2334/0x2bd0 kernel/exit.c:845 dogroupexit+0x108/0x2c8 kernel/exit.c:922 getsignal+0x4e4/0x2a88 kernel/signal.c:2781 dosignal arch/arm64/kernel/signal.c:882 [inline] donotifyresume+0x300/0x970 arch/arm64/kernel/signal.c:936 workpending+0xc/0x2dc
Allocated by task 0: slabpostallochook+0x50/0x5c0 mm/slab.h:516 slaballocnode mm/slub.c:2907 [inline] slaballoc mm/slub.c:2915 [inline] kmemcachealloc+0x1f4/0x4c0 mm/slub.c:2920 allocpid+0xdc/0xc00 kernel/pid.c:180 copyprocess+0x2794/0x5e18 kernel/fork.c:2129 kernelclone+0x194/0x13c8 kernel/fork.c:2500 kernelthread+0xd4/0x110 kernel/fork.c:2552 restinit+0x44/0x4a0 init/main.c:687 archcallrestinit+0x1c/0x28 startkernel+0x520/0x554 init/main.c:1064 0x0
Freed by task 270: slabfreehook mm/slub.c:1562 [inline] slabfreefreelisthook+0x98/0x260 mm/slub.c:1600 slabfree mm/slub.c:3161 [inline] kmemcachefree+0x224/0x8e0 mm/slub.c:3177 putpid.part.4+0xe0/0x1a8 kernel/pid.c:114 putpid+0x30/0x48 kernel/pid.c:109 procdocadpid+0x190/0x1b0 kernel/sysctl.c:1401 procsyscallhandler+0x338/0x4b0 fs/proc/procsysctl.c:591 procsyswrite+0x34/0x48 fs/proc/procsysctl.c:617 callwriteiter include/linux/fs.h:1977 [inline] newsyncwrite+0x3ac/0x510 fs/readwrite.c:518 vfswrite fs/readwrite.c:605 [inline] vfswrite+0x9c4/0x1018 fs/readwrite.c:585 ksyswrite+0x124/0x240 fs/readwrite.c:658 dosyswrite fs/readwrite.c:670 [inline] sesyswrite fs/readwrite.c:667 [inline] arm64syswrite+0x78/0xb0 fs/readwrite.c:667 invokesyscall arch/arm64/kernel/syscall.c:37 [inline] invokesyscall arch/arm64/kernel/syscall.c:49 [inline] el0svccommon.constprop.1+0x16c/0x388 arch/arm64/kernel/syscall.c:129 doel0svc+0xf8/0x150 arch/arm64/kernel/syscall.c:168 el0svc+0x28/0x38 arch/arm64/kernel/entry-common.c:416 el0synchandler+0x134/0x180 arch/arm64/kernel/entry-common.c:432 el0sync+0x154/0x180 arch/arm64/kernel/entry.S:701
The buggy address belongs to the object at ffff23794dda0000 which belongs to the cache pid of size 224 The buggy address is located 4 bytes inside of 224-byte region [ff ---truncated---
Other sources
In the Linux kernel, the following vulnerability has been resolved:
pid: take a reference when initializing cadpid
The Linux kernel CVE team has assigned CVE-2021-47118 to this issue.
Upstream advisory: https://lore.kernel.org/linux-cve-announce/2024031509-CVE-2021-47118-faf2@gregkh/T/#u
— Red Hat
Affected Software
Remediation
Event History
Frequently Asked Questions
What is the severity of CVE-2021-47118?
The severity of CVE-2021-47118 is classified as moderate.
How do I fix CVE-2021-47118?
To fix CVE-2021-47118, update to the fixed versions of the Linux kernel provided by your vendor.
Which versions of the Linux kernel are affected by CVE-2021-47118?
CVE-2021-47118 affects Linux kernel versions prior to 4.4.272, 4.9.272, 4.14.236, 4.19.194, 5.4.125, 5.10.43, 5.12.10, and 5.13.
Is there a workaround for CVE-2021-47118?
There are no specific workarounds recommended for CVE-2021-47118; the best practice is to update the kernel.
Who is impacted by CVE-2021-47118?
Users of the affected Linux kernel versions, particularly those running on Red Hat and Debian systems, are impacted by CVE-2021-47118.