Skip to content

Commit 358d183

Browse files
pvts-matPlaidCat
authored andcommitted
x86/entry: Do not allow external 0x80 interrupts
jira VULN-772 cve CVE-2024-25744 commit-author Thomas Gleixner <[email protected]> commit 55617fb The INT 0x80 instruction is used for 32-bit x86 Linux syscalls. The kernel expects to receive a software interrupt as a result of the INT 0x80 instruction. However, an external interrupt on the same vector also triggers the same codepath. An external interrupt on vector 0x80 will currently be interpreted as a 32-bit system call, and assuming that it was a user context. Panic on external interrupts on the vector. To distinguish software interrupts from external ones, the kernel checks the APIC ISR bit relevant to the 0x80 vector. For software interrupts, this bit will be 0. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: Borislav Petkov (AMD) <[email protected]> Cc: <[email protected]> # v6.0+ (cherry picked from commit 55617fb) Signed-off-by: Marcin Wcisło <[email protected]>
1 parent 7c17707 commit 358d183

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

arch/x86/entry/common.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <xen/events.h>
2727
#endif
2828

29+
#include <asm/apic.h>
2930
#include <asm/desc.h>
3031
#include <asm/traps.h>
3132
#include <asm/vdso.h>
@@ -127,6 +128,25 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr)
127128
}
128129

129130
#ifdef CONFIG_IA32_EMULATION
131+
static __always_inline bool int80_is_external(void)
132+
{
133+
const unsigned int offs = (0x80 / 32) * 0x10;
134+
const u32 bit = BIT(0x80 % 32);
135+
136+
/* The local APIC on XENPV guests is fake */
137+
if (cpu_feature_enabled(X86_FEATURE_XENPV))
138+
return false;
139+
140+
/*
141+
* If vector 0x80 is set in the APIC ISR then this is an external
142+
* interrupt. Either from broken hardware or injected by a VMM.
143+
*
144+
* Note: In guest mode this is only valid for secure guests where
145+
* the secure module fully controls the vAPIC exposed to the guest.
146+
*/
147+
return apic_read(APIC_ISR + offs) & bit;
148+
}
149+
130150
/**
131151
* int80_emulation - 32-bit legacy syscall entry
132152
*
@@ -150,12 +170,27 @@ DEFINE_IDTENTRY_RAW(int80_emulation)
150170
{
151171
int nr;
152172

153-
/* Establish kernel context. */
173+
/* Kernel does not use INT $0x80! */
174+
if (unlikely(!user_mode(regs))) {
175+
irqentry_enter(regs);
176+
instrumentation_begin();
177+
panic("Unexpected external interrupt 0x80\n");
178+
}
179+
180+
/*
181+
* Establish kernel context for instrumentation, including for
182+
* int80_is_external() below which calls into the APIC driver.
183+
* Identical for soft and external interrupts.
184+
*/
154185
enter_from_user_mode(regs);
155186

156187
instrumentation_begin();
157188
add_random_kstack_offset();
158189

190+
/* Validate that this is a soft interrupt to the extent possible */
191+
if (unlikely(int80_is_external()))
192+
panic("Unexpected external interrupt 0x80\n");
193+
159194
/*
160195
* The low level idtentry code pushed -1 into regs::orig_ax
161196
* and regs::ax contains the syscall number.

0 commit comments

Comments
 (0)