Skip to content

Commit 62cd6a7

Browse files
pvts-matPlaidCat
authored andcommitted
x86/entry: Make IA32 syscalls' availability depend on ia32_enabled()
jira VULN-772 cve-pre CVE-2024-25744 commit-author Nikolay Borisov <nik.borisov@suse.com> commit 6138228 upstream-diff Upstream code between the #ifdef / #else / #endif in `arch/x86/kernel/cpu/common.c' differs slightly from `ciqlts9_2' (`wrmsrl_cstar' function used instead of `wrmsrl'). Applied the same logic of #ifdef / #else -> if / else conversion to the existing codebase. Another major aspect of supporting running of 32bit processes is the ability to access 32bit syscalls. Such syscalls can be invoked by using the legacy int 0x80 handler and sysenter/syscall instructions. If IA32 emulation is disabled ensure that each of those 3 distinct mechanisms are also disabled. For int 0x80 a #GP exception would be generated since the respective descriptor is not going to be loaded at all. Invoking sysenter will also result in a #GP since IA32_SYSENTER_CS contains an invalid segment. Finally, syscall instruction cannot really be disabled so it's configured to execute a minimal handler. Signed-off-by: Nikolay Borisov <nik.borisov@suse.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/20230623111409.3047467-6-nik.borisov@suse.com (cherry picked from commit 6138228) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent 6bbbcea commit 62cd6a7

File tree

3 files changed

+29
-18
lines changed

3 files changed

+29
-18
lines changed

arch/x86/include/asm/proto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ void entry_INT80_compat(void);
3636
#ifdef CONFIG_XEN_PV
3737
void xen_entry_INT80_compat(void);
3838
#endif
39+
#else /* !CONFIG_IA32_EMULATION */
40+
#define entry_SYSCALL_compat NULL
41+
#define entry_SYSENTER_compat NULL
3942
#endif
4043

4144
void x86_configure_nx(void);

arch/x86/kernel/cpu/common.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include <asm/cpu_device_id.h>
6060
#include <asm/uv/uv.h>
6161
#include <asm/sigframe.h>
62+
#include <asm/ia32.h>
6263
#include <asm/traps.h>
6364
#include <asm/sev.h>
6465

@@ -2012,24 +2013,24 @@ void syscall_init(void)
20122013
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
20132014
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
20142015

2015-
#ifdef CONFIG_IA32_EMULATION
2016-
wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL_compat);
2017-
/*
2018-
* This only works on Intel CPUs.
2019-
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
2020-
* This does not cause SYSENTER to jump to the wrong location, because
2021-
* AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
2022-
*/
2023-
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
2024-
wrmsrl_safe(MSR_IA32_SYSENTER_ESP,
2025-
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
2026-
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
2027-
#else
2028-
wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL32_ignore);
2029-
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
2030-
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
2031-
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
2032-
#endif
2016+
if (ia32_enabled()) {
2017+
wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL_compat);
2018+
/*
2019+
* This only works on Intel CPUs.
2020+
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
2021+
* This does not cause SYSENTER to jump to the wrong location, because
2022+
* AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
2023+
*/
2024+
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
2025+
wrmsrl_safe(MSR_IA32_SYSENTER_ESP,
2026+
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
2027+
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
2028+
} else {
2029+
wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL32_ignore);
2030+
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
2031+
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
2032+
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
2033+
}
20332034

20342035
/*
20352036
* Flags to clear on syscall; clear as much as possible

arch/x86/kernel/idt.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <asm/proto.h>
1111
#include <asm/desc.h>
1212
#include <asm/hw_irq.h>
13+
#include <asm/ia32.h>
1314
#include <asm/idtentry.h>
1415

1516
#define DPL0 0x0
@@ -116,6 +117,9 @@ static const __initconst struct idt_data def_idts[] = {
116117
#endif
117118

118119
SYSG(X86_TRAP_OF, asm_exc_overflow),
120+
};
121+
122+
static const struct idt_data ia32_idt[] __initconst = {
119123
#if defined(CONFIG_IA32_EMULATION)
120124
SYSG(IA32_SYSCALL_VECTOR, entry_INT80_compat),
121125
#elif defined(CONFIG_X86_32)
@@ -226,6 +230,9 @@ void __init idt_setup_early_traps(void)
226230
void __init idt_setup_traps(void)
227231
{
228232
idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true);
233+
234+
if (ia32_enabled())
235+
idt_setup_from_table(idt_table, ia32_idt, ARRAY_SIZE(ia32_idt), true);
229236
}
230237

231238
#ifdef CONFIG_X86_64

0 commit comments

Comments
 (0)