CVE-2021-46957 Information
Description
In the Linux kernel the following vulnerability has been resolved:
riscv/kprobe: fix kernel panic when invoking sys_read traced by kprobe
The execution of sys_read end up hitting a BUG_ON() in __find_get_block after installing kprobe at sys_read the BUG message like the following:
[ 65.708663] ————[ cut here ]————
[ 65.709987] kernel BUG at fs/buffer.c:1251!
[ 65.711283] Kernel BUG [1]
[ 65.712032] Modules linked in:
[ 65.712925] CPU: 0 PID: 51 Comm: sh Not tainted 5.12.0-rc4 1
[ 65.714407] Hardware name: riscv-virtioqemu (DT)
[ 65.715696] epc : __find_get_block+0x218/0x2c8
[ 65.716835] ra : __getblk_gfp+0x1c/0x4a
[ 65.717831] epc : ffffffe00019f11e ra : ffffffe00019f56a sp : ffffffe002437930
[ 65.719553] gp : ffffffe000f06030 tp : ffffffe0015abc00 t0 : ffffffe00191e038
[ 65.721290] t1 : ffffffe00191e038 t2 : 000000000000000a s0 : ffffffe002437960
[ 65.723051] s1 : ffffffe00160ad00 a0 : ffffffe00160ad00 a1 : 000000000000012a
[ 65.724772] a2 : 0000000000000400 a3 : 0000000000000008 a4 : 0000000000000040
[ 65.726545] a5 : 0000000000000000 a6 : ffffffe00191e000 a7 : 0000000000000000
[ 65.728308] s2 : 000000000000012a s3 : 0000000000000400 s4 : 0000000000000008
[ 65.730049] s5 : 000000000000006c s6 : ffffffe00240f800 s7 : ffffffe000f080a8
[ 65.731802] s8 : 0000000000000001 s9 : 000000000000012a s10: 0000000000000008
[ 65.733516] s11: 0000000000000008 t3 : 00000000000003ff t4 : 000000000000000f
[ 65.734434] t5 : 00000000000003ff t6 : 0000000000040000
[ 65.734613] status: 0000000000000100 badaddr: 0000000000000000 cause: 0000000000000003
[ 65.734901] Call Trace:
[ 65.735076] [
A simple reproducer looks like: echo ‘p:myprobe sys_read fd=%a0 buf=%a1 count=%a2’ > /sys/kernel/debug/tracing/kprobe_events echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable cat /sys/kernel/debug/tracing/trace
Here’s what happens to hit that BUG_ON():
-
After installing kprobe at entry of sys_read the first instruction is replaced by ’ebreak’ instruction on riscv64 platform.
-
Once kernel reach the ’ebreak’ instruction at the entry of sys_read it trap into the riscv breakpoint handler where it do something to setup for coming single-step of origin instruction including backup the ‘sstatus’ in pt_regs followed by disable interrupt during single stepping via clear ‘SIE’ bit of ‘sstatus’ in pt_regs.
-
Then kernel restore to the instruction slot contains two instructions one is original instruction at entry of sys_read the other is ’ebreak’. Here it trigger a ‘Instruction page fault’ exception (value at ‘scause’ is ‘0xc’) if PF is not filled into PageTabe for that slot yet.
-
Again kernel trap into page fault exception handler where it choose different policy according to the state of running kprobe. Because afte 2) the state is KPROBE_HIT_SS so kernel reset the current kp
truncated—
Reference
https://git.kernel.org/stable/c/fd0f06590d35c99f98d12c7984897ec4201a6263 https://git.kernel.org/stable/c/b1ebaa0e1318494a7637099a26add50509e37964
Share on: