]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
37e91b0cbd232edaa64d419babc70fed0eebcd3f
[thirdparty/kernel/stable-queue.git] /
1 From f5d03da48d062966c94f0199d20be0b3a37a7982 Mon Sep 17 00:00:00 2001
2 From: Jinghao Jia <jinghao7@illinois.edu>
3 Date: Tue, 2 Jan 2024 17:33:45 -0600
4 Subject: x86/kprobes: fix incorrect return address calculation in kprobe_emulate_call_indirect
5
6 From: Jinghao Jia <jinghao7@illinois.edu>
7
8 commit f5d03da48d062966c94f0199d20be0b3a37a7982 upstream.
9
10 kprobe_emulate_call_indirect currently uses int3_emulate_call to emulate
11 indirect calls. However, int3_emulate_call always assumes the size of
12 the call to be 5 bytes when calculating the return address. This is
13 incorrect for register-based indirect calls in x86, which can be either
14 2 or 3 bytes depending on whether REX prefix is used. At kprobe runtime,
15 the incorrect return address causes control flow to land onto the wrong
16 place after return -- possibly not a valid instruction boundary. This
17 can lead to a panic like the following:
18
19 [ 7.308204][ C1] BUG: unable to handle page fault for address: 000000000002b4d8
20 [ 7.308883][ C1] #PF: supervisor read access in kernel mode
21 [ 7.309168][ C1] #PF: error_code(0x0000) - not-present page
22 [ 7.309461][ C1] PGD 0 P4D 0
23 [ 7.309652][ C1] Oops: 0000 [#1] SMP
24 [ 7.309929][ C1] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.7.0-rc5-trace-for-next #6
25 [ 7.310397][ C1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-20220807_005459-localhost 04/01/2014
26 [ 7.311068][ C1] RIP: 0010:__common_interrupt+0x52/0xc0
27 [ 7.311349][ C1] Code: 01 00 4d 85 f6 74 39 49 81 fe 00 f0 ff ff 77 30 4c 89 f7 4d 8b 5e 68 41 ba 91 76 d8 42 45 03 53 fc 74 02 0f 0b cc ff d3 65 48 <8b> 05 30 c7 ff 7e 65 4c 89 3d 28 c7 ff 7e 5b 41 5c 41 5e 41 5f c3
28 [ 7.312512][ C1] RSP: 0018:ffffc900000e0fd0 EFLAGS: 00010046
29 [ 7.312899][ C1] RAX: 0000000000000001 RBX: 0000000000000023 RCX: 0000000000000001
30 [ 7.313334][ C1] RDX: 00000000000003cd RSI: 0000000000000001 RDI: ffff888100d302a4
31 [ 7.313702][ C1] RBP: 0000000000000001 R08: 0ef439818636191f R09: b1621ff338a3b482
32 [ 7.314146][ C1] R10: ffffffff81e5127b R11: ffffffff81059810 R12: 0000000000000023
33 [ 7.314509][ C1] R13: 0000000000000000 R14: ffff888100d30200 R15: 0000000000000000
34 [ 7.314951][ C1] FS: 0000000000000000(0000) GS:ffff88813bc80000(0000) knlGS:0000000000000000
35 [ 7.315396][ C1] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
36 [ 7.315691][ C1] CR2: 000000000002b4d8 CR3: 0000000003028003 CR4: 0000000000370ef0
37 [ 7.316153][ C1] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
38 [ 7.316508][ C1] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
39 [ 7.316948][ C1] Call Trace:
40 [ 7.317123][ C1] <IRQ>
41 [ 7.317279][ C1] ? __die_body+0x64/0xb0
42 [ 7.317482][ C1] ? page_fault_oops+0x248/0x370
43 [ 7.317712][ C1] ? __wake_up+0x96/0xb0
44 [ 7.317964][ C1] ? exc_page_fault+0x62/0x130
45 [ 7.318211][ C1] ? asm_exc_page_fault+0x22/0x30
46 [ 7.318444][ C1] ? __cfi_native_send_call_func_single_ipi+0x10/0x10
47 [ 7.318860][ C1] ? default_idle+0xb/0x10
48 [ 7.319063][ C1] ? __common_interrupt+0x52/0xc0
49 [ 7.319330][ C1] common_interrupt+0x78/0x90
50 [ 7.319546][ C1] </IRQ>
51 [ 7.319679][ C1] <TASK>
52 [ 7.319854][ C1] asm_common_interrupt+0x22/0x40
53 [ 7.320082][ C1] RIP: 0010:default_idle+0xb/0x10
54 [ 7.320309][ C1] Code: 4c 01 c7 4c 29 c2 e9 72 ff ff ff cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 b8 0c 67 40 a5 66 90 0f 00 2d 09 b9 3b 00 fb f4 <fa> c3 0f 1f 00 90 90 90 90 90 90 90 90 90 90 90 b8 0c 67 40 a5 e9
55 [ 7.321449][ C1] RSP: 0018:ffffc9000009bee8 EFLAGS: 00000256
56 [ 7.321808][ C1] RAX: ffff88813bca8b68 RBX: 0000000000000001 RCX: 000000000001ef0c
57 [ 7.322227][ C1] RDX: 0000000000000000 RSI: 0000000000000001 RDI: 000000000001ef0c
58 [ 7.322656][ C1] RBP: ffffc9000009bef8 R08: 8000000000000000 R09: 00000000000008c2
59 [ 7.323083][ C1] R10: 0000000000000000 R11: ffffffff81058e70 R12: 0000000000000000
60 [ 7.323530][ C1] R13: ffff8881002b30c0 R14: 0000000000000000 R15: 0000000000000000
61 [ 7.323948][ C1] ? __cfi_lapic_next_deadline+0x10/0x10
62 [ 7.324239][ C1] default_idle_call+0x31/0x50
63 [ 7.324464][ C1] do_idle+0xd3/0x240
64 [ 7.324690][ C1] cpu_startup_entry+0x25/0x30
65 [ 7.324983][ C1] start_secondary+0xb4/0xc0
66 [ 7.325217][ C1] secondary_startup_64_no_verify+0x179/0x17b
67 [ 7.325498][ C1] </TASK>
68 [ 7.325641][ C1] Modules linked in:
69 [ 7.325906][ C1] CR2: 000000000002b4d8
70 [ 7.326104][ C1] ---[ end trace 0000000000000000 ]---
71 [ 7.326354][ C1] RIP: 0010:__common_interrupt+0x52/0xc0
72 [ 7.326614][ C1] Code: 01 00 4d 85 f6 74 39 49 81 fe 00 f0 ff ff 77 30 4c 89 f7 4d 8b 5e 68 41 ba 91 76 d8 42 45 03 53 fc 74 02 0f 0b cc ff d3 65 48 <8b> 05 30 c7 ff 7e 65 4c 89 3d 28 c7 ff 7e 5b 41 5c 41 5e 41 5f c3
73 [ 7.327570][ C1] RSP: 0018:ffffc900000e0fd0 EFLAGS: 00010046
74 [ 7.327910][ C1] RAX: 0000000000000001 RBX: 0000000000000023 RCX: 0000000000000001
75 [ 7.328273][ C1] RDX: 00000000000003cd RSI: 0000000000000001 RDI: ffff888100d302a4
76 [ 7.328632][ C1] RBP: 0000000000000001 R08: 0ef439818636191f R09: b1621ff338a3b482
77 [ 7.329223][ C1] R10: ffffffff81e5127b R11: ffffffff81059810 R12: 0000000000000023
78 [ 7.329780][ C1] R13: 0000000000000000 R14: ffff888100d30200 R15: 0000000000000000
79 [ 7.330193][ C1] FS: 0000000000000000(0000) GS:ffff88813bc80000(0000) knlGS:0000000000000000
80 [ 7.330632][ C1] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
81 [ 7.331050][ C1] CR2: 000000000002b4d8 CR3: 0000000003028003 CR4: 0000000000370ef0
82 [ 7.331454][ C1] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
83 [ 7.331854][ C1] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
84 [ 7.332236][ C1] Kernel panic - not syncing: Fatal exception in interrupt
85 [ 7.332730][ C1] Kernel Offset: disabled
86 [ 7.333044][ C1] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---
87
88 The relevant assembly code is (from objdump, faulting address
89 highlighted):
90
91 ffffffff8102ed9d: 41 ff d3 call *%r11
92 ffffffff8102eda0: 65 48 <8b> 05 30 c7 ff mov %gs:0x7effc730(%rip),%rax
93
94 The emulation incorrectly sets the return address to be ffffffff8102ed9d
95 + 0x5 = ffffffff8102eda2, which is the 8b byte in the middle of the next
96 mov. This in turn causes incorrect subsequent instruction decoding and
97 eventually triggers the page fault above.
98
99 Instead of invoking int3_emulate_call, perform push and jmp emulation
100 directly in kprobe_emulate_call_indirect. At this point we can obtain
101 the instruction size from p->ainsn.size so that we can calculate the
102 correct return address.
103
104 Link: https://lore.kernel.org/all/20240102233345.385475-1-jinghao7@illinois.edu/
105
106 Fixes: 6256e668b7af ("x86/kprobes: Use int3 instead of debug trap for single-step")
107 Cc: stable@vger.kernel.org
108 Signed-off-by: Jinghao Jia <jinghao7@illinois.edu>
109 Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
110 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
111 ---
112 arch/x86/kernel/kprobes/core.c | 3 ++-
113 1 file changed, 2 insertions(+), 1 deletion(-)
114
115 --- a/arch/x86/kernel/kprobes/core.c
116 +++ b/arch/x86/kernel/kprobes/core.c
117 @@ -569,7 +569,8 @@ static void kprobe_emulate_call_indirect
118 {
119 unsigned long offs = addrmode_regoffs[p->ainsn.indirect.reg];
120
121 - int3_emulate_call(regs, regs_get_register(regs, offs));
122 + int3_emulate_push(regs, regs->ip - INT3_INSN_SIZE + p->ainsn.size);
123 + int3_emulate_jmp(regs, regs_get_register(regs, offs));
124 }
125 NOKPROBE_SYMBOL(kprobe_emulate_call_indirect);
126