Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fb79944

Browse files
jpoimboePeter Zijlstra
authored andcommitted
x86,objtool: Split UNWIND_HINT_EMPTY in two
Mark reported that the ORC unwinder incorrectly marks an unwind as reliable when the unwind terminates prematurely in the dark corners of return_to_handler() due to lack of information about the next frame. The problem is UNWIND_HINT_EMPTY is used in two different situations: 1) The end of the kernel stack unwind before hitting user entry, boot code, or fork entry 2) A blind spot in ORC coverage where the unwinder has to bail due to lack of information about the next frame The ORC unwinder has no way to tell the difference between the two. When it encounters an undefined stack state with 'end=1', it blindly marks the stack reliable, which can break the livepatch consistency model. Fix it by splitting UNWIND_HINT_EMPTY into UNWIND_HINT_UNDEFINED and UNWIND_HINT_END_OF_STACK. Reported-by: Mark Rutland <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: Steven Rostedt (Google) <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/r/fd6212c8b450d3564b855e1cb48404d6277b4d9f.1677683419.git.jpoimboe@kernel.org
1 parent 4708ea1 commit fb79944

File tree

20 files changed

+116
-95
lines changed

20 files changed

+116
-95
lines changed

Documentation/livepatch/reliable-stacktrace.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ trampoline or return trampoline. For example, considering the x86_64
183183
.. code-block:: none
184184
185185
SYM_CODE_START(return_to_handler)
186-
UNWIND_HINT_EMPTY
186+
UNWIND_HINT_UNDEFINED
187187
subq $24, %rsp
188188
189189
/* Save the return values */

arch/x86/entry/entry_64.S

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ syscall_return_via_sysret:
205205
*/
206206
movq %rsp, %rdi
207207
movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
208-
UNWIND_HINT_EMPTY
208+
UNWIND_HINT_END_OF_STACK
209209

210210
pushq RSP-RDI(%rdi) /* RSP */
211211
pushq (%rdi) /* RDI */
@@ -286,7 +286,7 @@ SYM_FUNC_END(__switch_to_asm)
286286
.pushsection .text, "ax"
287287
__FUNC_ALIGN
288288
SYM_CODE_START_NOALIGN(ret_from_fork)
289-
UNWIND_HINT_EMPTY
289+
UNWIND_HINT_END_OF_STACK
290290
ANNOTATE_NOENDBR // copy_thread
291291
CALL_DEPTH_ACCOUNT
292292
movq %rax, %rdi
@@ -303,7 +303,7 @@ SYM_CODE_START_NOALIGN(ret_from_fork)
303303

304304
1:
305305
/* kernel thread */
306-
UNWIND_HINT_EMPTY
306+
UNWIND_HINT_END_OF_STACK
307307
movq %r12, %rdi
308308
CALL_NOSPEC rbx
309309
/*
@@ -643,7 +643,7 @@ SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL)
643643
*/
644644
movq %rsp, %rdi
645645
movq PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
646-
UNWIND_HINT_EMPTY
646+
UNWIND_HINT_END_OF_STACK
647647

648648
/* Copy the IRET frame to the trampoline stack. */
649649
pushq 6*8(%rdi) /* SS */
@@ -869,7 +869,7 @@ SYM_CODE_END(exc_xen_hypervisor_callback)
869869
*/
870870
__FUNC_ALIGN
871871
SYM_CODE_START_NOALIGN(xen_failsafe_callback)
872-
UNWIND_HINT_EMPTY
872+
UNWIND_HINT_UNDEFINED
873873
ENDBR
874874
movl %ds, %ecx
875875
cmpw %cx, 0x10(%rsp)
@@ -1520,7 +1520,7 @@ SYM_CODE_END(asm_exc_nmi)
15201520
* MSRs to fully disable 32-bit SYSCALL.
15211521
*/
15221522
SYM_CODE_START(ignore_sysret)
1523-
UNWIND_HINT_EMPTY
1523+
UNWIND_HINT_END_OF_STACK
15241524
ENDBR
15251525
mov $-ENOSYS, %eax
15261526
sysretl

arch/x86/include/asm/orc_types.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@
3939
#define ORC_REG_SP_INDIRECT 9
4040
#define ORC_REG_MAX 15
4141

42-
#define ORC_TYPE_CALL 0
43-
#define ORC_TYPE_REGS 1
44-
#define ORC_TYPE_REGS_PARTIAL 2
42+
#define ORC_TYPE_UNDEFINED 0
43+
#define ORC_TYPE_END_OF_STACK 1
44+
#define ORC_TYPE_CALL 2
45+
#define ORC_TYPE_REGS 3
46+
#define ORC_TYPE_REGS_PARTIAL 4
4547

4648
#ifndef __ASSEMBLY__
4749
#include <asm/byteorder.h>
@@ -60,16 +62,14 @@ struct orc_entry {
6062
#if defined(__LITTLE_ENDIAN_BITFIELD)
6163
unsigned sp_reg:4;
6264
unsigned bp_reg:4;
63-
unsigned type:2;
65+
unsigned type:3;
6466
unsigned signal:1;
65-
unsigned end:1;
6667
#elif defined(__BIG_ENDIAN_BITFIELD)
6768
unsigned bp_reg:4;
6869
unsigned sp_reg:4;
6970
unsigned unused:4;
70-
unsigned end:1;
7171
unsigned signal:1;
72-
unsigned type:2;
72+
unsigned type:3;
7373
#endif
7474
} __packed;
7575

arch/x86/include/asm/unwind_hints.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77

88
#ifdef __ASSEMBLY__
99

10-
.macro UNWIND_HINT_EMPTY
11-
UNWIND_HINT type=UNWIND_HINT_TYPE_CALL end=1
10+
.macro UNWIND_HINT_END_OF_STACK
11+
UNWIND_HINT type=UNWIND_HINT_TYPE_END_OF_STACK
12+
.endm
13+
14+
.macro UNWIND_HINT_UNDEFINED
15+
UNWIND_HINT type=UNWIND_HINT_TYPE_UNDEFINED
1216
.endm
1317

1418
.macro UNWIND_HINT_ENTRY
1519
VALIDATE_UNRET_BEGIN
16-
UNWIND_HINT_EMPTY
20+
UNWIND_HINT_END_OF_STACK
1721
.endm
1822

1923
.macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 partial=0 signal=1
@@ -73,7 +77,7 @@
7377
#else
7478

7579
#define UNWIND_HINT_FUNC \
76-
UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0, 0)
80+
UNWIND_HINT(UNWIND_HINT_TYPE_FUNC, ORC_REG_SP, 8, 0)
7781

7882
#endif /* __ASSEMBLY__ */
7983

arch/x86/kernel/ftrace_64.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ STACK_FRAME_NON_STANDARD_FP(__fentry__)
340340

341341
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
342342
SYM_CODE_START(return_to_handler)
343-
UNWIND_HINT_EMPTY
343+
UNWIND_HINT_UNDEFINED
344344
ANNOTATE_NOENDBR
345345
subq $16, %rsp
346346

arch/x86/kernel/head_64.S

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ L3_START_KERNEL = pud_index(__START_KERNEL_map)
4242
__HEAD
4343
.code64
4444
SYM_CODE_START_NOALIGN(startup_64)
45-
UNWIND_HINT_EMPTY
45+
UNWIND_HINT_END_OF_STACK
4646
/*
4747
* At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,
4848
* and someone has loaded an identity mapped page table
@@ -105,7 +105,7 @@ SYM_CODE_START_NOALIGN(startup_64)
105105
lretq
106106

107107
.Lon_kernel_cs:
108-
UNWIND_HINT_EMPTY
108+
UNWIND_HINT_END_OF_STACK
109109

110110
/* Sanitize CPU configuration */
111111
call verify_cpu
@@ -127,7 +127,7 @@ SYM_CODE_START_NOALIGN(startup_64)
127127
SYM_CODE_END(startup_64)
128128

129129
SYM_CODE_START(secondary_startup_64)
130-
UNWIND_HINT_EMPTY
130+
UNWIND_HINT_END_OF_STACK
131131
ANNOTATE_NOENDBR
132132
/*
133133
* At this point the CPU runs in 64bit mode CS.L = 1 CS.D = 0,
@@ -156,7 +156,7 @@ SYM_CODE_START(secondary_startup_64)
156156
* verify_cpu() above to make sure NX is enabled.
157157
*/
158158
SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
159-
UNWIND_HINT_EMPTY
159+
UNWIND_HINT_END_OF_STACK
160160
ANNOTATE_NOENDBR
161161

162162
/*
@@ -238,7 +238,7 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL)
238238
ANNOTATE_RETPOLINE_SAFE
239239
jmp *%rax
240240
1:
241-
UNWIND_HINT_EMPTY
241+
UNWIND_HINT_END_OF_STACK
242242
ANNOTATE_NOENDBR // above
243243

244244
/*
@@ -371,7 +371,7 @@ SYM_CODE_END(secondary_startup_64)
371371
*/
372372
SYM_CODE_START(start_cpu0)
373373
ANNOTATE_NOENDBR
374-
UNWIND_HINT_EMPTY
374+
UNWIND_HINT_END_OF_STACK
375375
movq initial_stack(%rip), %rsp
376376
jmp .Ljump_to_C_code
377377
SYM_CODE_END(start_cpu0)

arch/x86/kernel/relocate_kernel_64.S

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
.code64
4444
SYM_CODE_START_NOALIGN(relocate_range)
4545
SYM_CODE_START_NOALIGN(relocate_kernel)
46-
UNWIND_HINT_EMPTY
46+
UNWIND_HINT_END_OF_STACK
4747
ANNOTATE_NOENDBR
4848
/*
4949
* %rdi indirection_page
@@ -113,7 +113,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel)
113113
SYM_CODE_END(relocate_kernel)
114114

115115
SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
116-
UNWIND_HINT_EMPTY
116+
UNWIND_HINT_END_OF_STACK
117117
/* set return address to 0 if not preserving context */
118118
pushq $0
119119
/* store the start address on the stack */
@@ -231,7 +231,7 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped)
231231
SYM_CODE_END(identity_mapped)
232232

233233
SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
234-
UNWIND_HINT_EMPTY
234+
UNWIND_HINT_END_OF_STACK
235235
ANNOTATE_NOENDBR // RET target, above
236236
movq RSP(%r8), %rsp
237237
movq CR4(%r8), %rax
@@ -256,8 +256,8 @@ SYM_CODE_END(virtual_mapped)
256256

257257
/* Do the copies */
258258
SYM_CODE_START_LOCAL_NOALIGN(swap_pages)
259-
UNWIND_HINT_EMPTY
260-
movq %rdi, %rcx /* Put the page_list in %rcx */
259+
UNWIND_HINT_END_OF_STACK
260+
movq %rdi, %rcx /* Put the page_list in %rcx */
261261
xorl %edi, %edi
262262
xorl %esi, %esi
263263
jmp 1f

arch/x86/kernel/unwind_orc.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ static struct orc_entry orc_fp_entry = {
158158
.sp_offset = 16,
159159
.bp_reg = ORC_REG_PREV_SP,
160160
.bp_offset = -16,
161-
.end = 0,
162161
};
163162

164163
static struct orc_entry *orc_find(unsigned long ip)
@@ -250,13 +249,13 @@ static int orc_sort_cmp(const void *_a, const void *_b)
250249
return -1;
251250

252251
/*
253-
* The "weak" section terminator entries need to always be on the left
252+
* The "weak" section terminator entries need to always be first
254253
* to ensure the lookup code skips them in favor of real entries.
255254
* These terminator entries exist to handle any gaps created by
256255
* whitelisted .o files which didn't get objtool generation.
257256
*/
258257
orc_a = cur_orc_table + (a - cur_orc_ip_table);
259-
return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1;
258+
return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
260259
}
261260

262261
void unwind_module_init(struct module *mod, void *_orc_ip, size_t orc_ip_size,
@@ -474,14 +473,12 @@ bool unwind_next_frame(struct unwind_state *state)
474473
*/
475474
orc = &orc_fp_entry;
476475
state->error = true;
477-
}
478-
479-
/* End-of-stack check for kernel threads: */
480-
if (orc->sp_reg == ORC_REG_UNDEFINED) {
481-
if (!orc->end)
476+
} else {
477+
if (orc->type == ORC_TYPE_UNDEFINED)
482478
goto err;
483479

484-
goto the_end;
480+
if (orc->type == ORC_TYPE_END_OF_STACK)
481+
goto the_end;
485482
}
486483

487484
state->signal = orc->signal;

arch/x86/lib/retpoline.S

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
.align RETPOLINE_THUNK_SIZE
3535
SYM_INNER_LABEL(__x86_indirect_thunk_\reg, SYM_L_GLOBAL)
36-
UNWIND_HINT_EMPTY
36+
UNWIND_HINT_UNDEFINED
3737
ANNOTATE_NOENDBR
3838

3939
ALTERNATIVE_2 __stringify(RETPOLINE \reg), \
@@ -75,7 +75,7 @@ SYM_CODE_END(__x86_indirect_thunk_array)
7575
.align RETPOLINE_THUNK_SIZE
7676

7777
SYM_INNER_LABEL(__x86_indirect_call_thunk_\reg, SYM_L_GLOBAL)
78-
UNWIND_HINT_EMPTY
78+
UNWIND_HINT_UNDEFINED
7979
ANNOTATE_NOENDBR
8080

8181
CALL_DEPTH_ACCOUNT
@@ -103,7 +103,7 @@ SYM_CODE_END(__x86_indirect_call_thunk_array)
103103
.align RETPOLINE_THUNK_SIZE
104104

105105
SYM_INNER_LABEL(__x86_indirect_jump_thunk_\reg, SYM_L_GLOBAL)
106-
UNWIND_HINT_EMPTY
106+
UNWIND_HINT_UNDEFINED
107107
ANNOTATE_NOENDBR
108108
POLINE \reg
109109
ANNOTATE_UNRET_SAFE

arch/x86/platform/pvh/head.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
#define PVH_DS_SEL (PVH_GDT_ENTRY_DS * 8)
5151

5252
SYM_CODE_START_LOCAL(pvh_start_xen)
53-
UNWIND_HINT_EMPTY
53+
UNWIND_HINT_END_OF_STACK
5454
cld
5555

5656
lgdt (_pa(gdt))

0 commit comments

Comments
 (0)