Commit 61382281 authored by Nikolay Borisov's avatar Nikolay Borisov Committed by Thomas Gleixner

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: default avatarNikolay Borisov <nik.borisov@suse.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20230623111409.3047467-6-nik.borisov@suse.com
parent 5ae2702d
...@@ -36,6 +36,9 @@ void entry_INT80_compat(void); ...@@ -36,6 +36,9 @@ void entry_INT80_compat(void);
#ifdef CONFIG_XEN_PV #ifdef CONFIG_XEN_PV
void xen_entry_INT80_compat(void); void xen_entry_INT80_compat(void);
#endif #endif
#else /* !CONFIG_IA32_EMULATION */
#define entry_SYSCALL_compat NULL
#define entry_SYSENTER_compat NULL
#endif #endif
void x86_configure_nx(void); void x86_configure_nx(void);
......
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
#include <asm/intel-family.h> #include <asm/intel-family.h>
#include <asm/cpu_device_id.h> #include <asm/cpu_device_id.h>
#include <asm/uv/uv.h> #include <asm/uv/uv.h>
#include <asm/ia32.h>
#include <asm/set_memory.h> #include <asm/set_memory.h>
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/sev.h> #include <asm/sev.h>
...@@ -2074,24 +2075,24 @@ void syscall_init(void) ...@@ -2074,24 +2075,24 @@ void syscall_init(void)
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS); wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64); wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
#ifdef CONFIG_IA32_EMULATION if (ia32_enabled()) {
wrmsrl_cstar((unsigned long)entry_SYSCALL_compat); wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
/* /*
* This only works on Intel CPUs. * This only works on Intel CPUs.
* On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP. * On AMD CPUs these MSRs are 32-bit, CPU truncates MSR_IA32_SYSENTER_EIP.
* This does not cause SYSENTER to jump to the wrong location, because * This does not cause SYSENTER to jump to the wrong location, because
* AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit). * AMD doesn't allow SYSENTER in long mode (either 32- or 64-bit).
*/ */
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS); wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, wrmsrl_safe(MSR_IA32_SYSENTER_ESP,
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1)); (unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat); wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
#else } else {
wrmsrl_cstar((unsigned long)entry_SYSCALL32_ignore); wrmsrl_cstar((unsigned long)entry_SYSCALL32_ignore);
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG); wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL); wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL); wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
#endif }
/* /*
* Flags to clear on syscall; clear as much as possible * Flags to clear on syscall; clear as much as possible
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/ia32.h>
#include <asm/idtentry.h> #include <asm/idtentry.h>
#define DPL0 0x0 #define DPL0 0x0
...@@ -116,6 +117,9 @@ static const __initconst struct idt_data def_idts[] = { ...@@ -116,6 +117,9 @@ static const __initconst struct idt_data def_idts[] = {
#endif #endif
SYSG(X86_TRAP_OF, asm_exc_overflow), SYSG(X86_TRAP_OF, asm_exc_overflow),
};
static const struct idt_data ia32_idt[] __initconst = {
#if defined(CONFIG_IA32_EMULATION) #if defined(CONFIG_IA32_EMULATION)
SYSG(IA32_SYSCALL_VECTOR, entry_INT80_compat), SYSG(IA32_SYSCALL_VECTOR, entry_INT80_compat),
#elif defined(CONFIG_X86_32) #elif defined(CONFIG_X86_32)
...@@ -225,6 +229,9 @@ void __init idt_setup_early_traps(void) ...@@ -225,6 +229,9 @@ void __init idt_setup_early_traps(void)
void __init idt_setup_traps(void) void __init idt_setup_traps(void)
{ {
idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true); idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true);
if (ia32_enabled())
idt_setup_from_table(idt_table, ia32_idt, ARRAY_SIZE(ia32_idt), true);
} }
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment