Skip to content

Commit 6138228

Browse files
Nikolay BorisovKAGA-KOKO
authored andcommitted
x86/entry: Make IA32 syscalls' availability depend on ia32_enabled()
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 <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 5ae2702 commit 6138228

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
@@ -62,6 +62,7 @@
6262
#include <asm/intel-family.h>
6363
#include <asm/cpu_device_id.h>
6464
#include <asm/uv/uv.h>
65+
#include <asm/ia32.h>
6566
#include <asm/set_memory.h>
6667
#include <asm/traps.h>
6768
#include <asm/sev.h>
@@ -2074,24 +2075,24 @@ void syscall_init(void)
20742075
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
20752076
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
20762077

2077-
#ifdef CONFIG_IA32_EMULATION
2078-
wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
2079-
/*
2080-
* This only works on Intel CPUs.
2081-
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
2082-
* This does not cause SYSENTER to jump to the wrong location, because
2083-
* AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
2084-
*/
2085-
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
2086-
wrmsrl_safe(MSR_IA32_SYSENTER_ESP,
2087-
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
2088-
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
2089-
#else
2090-
wrmsrl_cstar((unsigned long)entry_SYSCALL32_ignore);
2091-
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
2092-
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
2093-
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
2094-
#endif
2078+
if (ia32_enabled()) {
2079+
wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
2080+
/*
2081+
* This only works on Intel CPUs.
2082+
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
2083+
* This does not cause SYSENTER to jump to the wrong location, because
2084+
* AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
2085+
*/
2086+
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
2087+
wrmsrl_safe(MSR_IA32_SYSENTER_ESP,
2088+
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
2089+
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
2090+
} else {
2091+
wrmsrl_cstar((unsigned long)entry_SYSCALL32_ignore);
2092+
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
2093+
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
2094+
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
2095+
}
20952096

20962097
/*
20972098
* 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)
@@ -225,6 +229,9 @@ void __init idt_setup_early_traps(void)
225229
void __init idt_setup_traps(void)
226230
{
227231
idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true);
232+
233+
if (ia32_enabled())
234+
idt_setup_from_table(idt_table, ia32_idt, ARRAY_SIZE(ia32_idt), true);
228235
}
229236

230237
#ifdef CONFIG_X86_64

0 commit comments

Comments
 (0)