CVE-2021-46957
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
27/02/2024
Last modified:
14/03/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
riscv/kprobe: fix kernel panic when invoking sys_read traced by kprobe<br />
<br />
The execution of sys_read end up hitting a BUG_ON() in __find_get_block<br />
after installing kprobe at sys_read, the BUG message like the following:<br />
<br />
[ 65.708663] ------------[ cut here ]------------<br />
[ 65.709987] kernel BUG at fs/buffer.c:1251!<br />
[ 65.711283] Kernel BUG [#1]<br />
[ 65.712032] Modules linked in:<br />
[ 65.712925] CPU: 0 PID: 51 Comm: sh Not tainted 5.12.0-rc4 #1<br />
[ 65.714407] Hardware name: riscv-virtio,qemu (DT)<br />
[ 65.715696] epc : __find_get_block+0x218/0x2c8<br />
[ 65.716835] ra : __getblk_gfp+0x1c/0x4a<br />
[ 65.717831] epc : ffffffe00019f11e ra : ffffffe00019f56a sp : ffffffe002437930<br />
[ 65.719553] gp : ffffffe000f06030 tp : ffffffe0015abc00 t0 : ffffffe00191e038<br />
[ 65.721290] t1 : ffffffe00191e038 t2 : 000000000000000a s0 : ffffffe002437960<br />
[ 65.723051] s1 : ffffffe00160ad00 a0 : ffffffe00160ad00 a1 : 000000000000012a<br />
[ 65.724772] a2 : 0000000000000400 a3 : 0000000000000008 a4 : 0000000000000040<br />
[ 65.726545] a5 : 0000000000000000 a6 : ffffffe00191e000 a7 : 0000000000000000<br />
[ 65.728308] s2 : 000000000000012a s3 : 0000000000000400 s4 : 0000000000000008<br />
[ 65.730049] s5 : 000000000000006c s6 : ffffffe00240f800 s7 : ffffffe000f080a8<br />
[ 65.731802] s8 : 0000000000000001 s9 : 000000000000012a s10: 0000000000000008<br />
[ 65.733516] s11: 0000000000000008 t3 : 00000000000003ff t4 : 000000000000000f<br />
[ 65.734434] t5 : 00000000000003ff t6 : 0000000000040000<br />
[ 65.734613] status: 0000000000000100 badaddr: 0000000000000000 cause: 0000000000000003<br />
[ 65.734901] Call Trace:<br />
[ 65.735076] [] __find_get_block+0x218/0x2c8<br />
[ 65.735417] [] __ext4_get_inode_loc+0xb2/0x2f6<br />
[ 65.735618] [] ext4_get_inode_loc+0x3a/0x8a<br />
[ 65.735802] [] ext4_reserve_inode_write+0x2e/0x8c<br />
[ 65.735999] [] __ext4_mark_inode_dirty+0x4c/0x18e<br />
[ 65.736208] [] ext4_dirty_inode+0x46/0x66<br />
[ 65.736387] [] __mark_inode_dirty+0x12c/0x3da<br />
[ 65.736576] [] touch_atime+0x146/0x150<br />
[ 65.736748] [] filemap_read+0x234/0x246<br />
[ 65.736920] [] generic_file_read_iter+0xc0/0x114<br />
[ 65.737114] [] ext4_file_read_iter+0x42/0xea<br />
[ 65.737310] [] new_sync_read+0xe2/0x15a<br />
[ 65.737483] [] vfs_read+0xca/0xf2<br />
[ 65.737641] [] ksys_read+0x5e/0xc8<br />
[ 65.737816] [] sys_read+0xe/0x16<br />
[ 65.737973] [] ret_from_syscall+0x0/0x2<br />
[ 65.738858] ---[ end trace fe93f985456c935d ]---<br />
<br />
A simple reproducer looks like:<br />
echo &#39;p:myprobe sys_read fd=%a0 buf=%a1 count=%a2&#39; > /sys/kernel/debug/tracing/kprobe_events<br />
echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable<br />
cat /sys/kernel/debug/tracing/trace<br />
<br />
Here&#39;s what happens to hit that BUG_ON():<br />
<br />
1) After installing kprobe at entry of sys_read, the first instruction<br />
is replaced by &#39;ebreak&#39; instruction on riscv64 platform.<br />
<br />
2) Once kernel reach the &#39;ebreak&#39; instruction at the entry of sys_read,<br />
it trap into the riscv breakpoint handler, where it do something to<br />
setup for coming single-step of origin instruction, including backup<br />
the &#39;sstatus&#39; in pt_regs, followed by disable interrupt during single<br />
stepping via clear &#39;SIE&#39; bit of &#39;sstatus&#39; in pt_regs.<br />
<br />
3) Then kernel restore to the instruction slot contains two instructions,<br />
one is original instruction at entry of sys_read, the other is &#39;ebreak&#39;.<br />
Here it trigger a &#39;Instruction page fault&#39; exception (value at &#39;scause&#39;<br />
is &#39;0xc&#39;), if PF is not filled into PageTabe for that slot yet.<br />
<br />
4) Again kernel trap into page fault exception handler, where it choose<br />
different policy according to the state of running kprobe. Because<br />
afte 2) the state is KPROBE_HIT_SS, so kernel reset the current kp<br />
---truncated---
Impact
Base Score 3.x
5.50
Severity 3.x
MEDIUM
Vulnerable products and versions
CPE | From | Up to |
---|---|---|
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.12 (including) | 5.12.3 (excluding) |
To consult the complete list of CPE names with products and versions, see this page