History

x86/entry/vdso32: Work around libgcc unwinder bug

The unwinder code in libgcc has a long standing bug which causes it to fail to pick up the signal frame CFI flag. This is a generic bug across all platforms. It affects the __kernel_sigreturn and __kernel_rt_sigreturn vdso entry points on i386. The x86-64 kernel doesn't provide a sigreturn stub, and so there is no kernel-provided code that is affected on x86-64. libgcc does have a legacy fallback path which happens to work as long as the bytes immediately before each of the sigreturn functions fall outside any function. This patch adds a nop before the ALIGN to each of the sigreturn stubs to ensure that this is, indeed, the case. The rest of the patch is just a comment which documents the invariants that need to be maintained for this legacy path to work correctly. This is a manifest bug: in the current vdso, __kernel_vsyscall is a multiple of 16 bytes long and thus __kernel_sigreturn does not have any padding in front of it.

H. Peter Anvin committed 8 months ago

Commit b5ef09a1 parent 59674fc1 file · +30 −0Browse files

Unified · Split

arch/x86/entry/vdso/vdso32/sigreturn.S+30−0
@@ -35,9 +35,38 @@ · 34 unmodified lines
35#endif35#endif
36.endm36.endm
37 37
38/*
39 * WARNING:
40 *
41 * A bug in the libgcc unwinder as of at least gcc 15.2 (2026) means that
42 * the unwinder fails to recognize the signal frame flag.
43 *
44 * There is a hacky legacy fallback path in libgcc which ends up
45 * getting invoked instead. It happens to work as long as BOTH of the
46 * following conditions are true:
47 *
48 * 1. There is at least one byte before the each of the sigreturn
49 * functions which falls outside any function. This is enforced by
50 * an explicit nop instruction before the ALIGN.
51 * 2. The code sequences between the entry point up to and including
52 * the int $0x80 below need to match EXACTLY. Do not change them
53 * in any way. The exact byte sequences are:
54 *
55 * __kernel_sigreturn:
56 * 0: 58 pop %eax
57 * 1: b8 77 00 00 00 mov $0x77,%eax
58 * 6: cd 80 int $0x80
59 *
60 * __kernel_rt_sigreturn:
61 * 0: b8 ad 00 00 00 mov $0xad,%eax
62 * 5: cd 80 int $0x80
63 *
64 * For details, see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124050
65 */
38 .text66 .text
39 .globl __kernel_sigreturn67 .globl __kernel_sigreturn
40 .type __kernel_sigreturn,@function68 .type __kernel_sigreturn,@function
69 nop /* libgcc hack: see comment above */
41 ALIGN70 ALIGN
42__kernel_sigreturn:71__kernel_sigreturn:
43 STARTPROC_SIGNAL_FRAME IA32_SIGFRAME_sigcontext72 STARTPROC_SIGNAL_FRAME IA32_SIGFRAME_sigcontext
@@ -52,6 +81,7 @@ SYM_INNER_LABEL(vdso32_sigreturn_landing_pad, SYM_L_GLOBAL) · 8 unmodified lines
52 81
53 .globl __kernel_rt_sigreturn82 .globl __kernel_rt_sigreturn
54 .type __kernel_rt_sigreturn,@function83 .type __kernel_rt_sigreturn,@function
84 nop /* libgcc hack: see comment above */
55 ALIGN85 ALIGN
56__kernel_rt_sigreturn:86__kernel_rt_sigreturn:
57 STARTPROC_SIGNAL_FRAME IA32_RT_SIGFRAME_sigcontext87 STARTPROC_SIGNAL_FRAME IA32_RT_SIGFRAME_sigcontext

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t