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 <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
This commit is contained in:
parent
5ae2702d7c
commit
61382281e9
@ -36,6 +36,9 @@ void entry_INT80_compat(void);
|
||||
#ifdef CONFIG_XEN_PV
|
||||
void xen_entry_INT80_compat(void);
|
||||
#endif
|
||||
#else /* !CONFIG_IA32_EMULATION */
|
||||
#define entry_SYSCALL_compat NULL
|
||||
#define entry_SYSENTER_compat NULL
|
||||
#endif
|
||||
|
||||
void x86_configure_nx(void);
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/uv/uv.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/set_memory.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/sev.h>
|
||||
@ -2074,24 +2075,24 @@ void syscall_init(void)
|
||||
wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS);
|
||||
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
|
||||
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
|
||||
/*
|
||||
* This only works on Intel CPUs.
|
||||
* 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
|
||||
* 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_ESP,
|
||||
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
|
||||
#else
|
||||
wrmsrl_cstar((unsigned long)entry_SYSCALL32_ignore);
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
|
||||
#endif
|
||||
if (ia32_enabled()) {
|
||||
wrmsrl_cstar((unsigned long)entry_SYSCALL_compat);
|
||||
/*
|
||||
* This only works on Intel CPUs.
|
||||
* 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
|
||||
* 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_ESP,
|
||||
(unsigned long)(cpu_entry_stack(smp_processor_id()) + 1));
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)entry_SYSENTER_compat);
|
||||
} else {
|
||||
wrmsrl_cstar((unsigned long)entry_SYSCALL32_ignore);
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)GDT_ENTRY_INVALID_SEG);
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
|
||||
wrmsrl_safe(MSR_IA32_SYSENTER_EIP, 0ULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flags to clear on syscall; clear as much as possible
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <asm/proto.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/hw_irq.h>
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/idtentry.h>
|
||||
|
||||
#define DPL0 0x0
|
||||
@ -116,6 +117,9 @@ static const __initconst struct idt_data def_idts[] = {
|
||||
#endif
|
||||
|
||||
SYSG(X86_TRAP_OF, asm_exc_overflow),
|
||||
};
|
||||
|
||||
static const struct idt_data ia32_idt[] __initconst = {
|
||||
#if defined(CONFIG_IA32_EMULATION)
|
||||
SYSG(IA32_SYSCALL_VECTOR, entry_INT80_compat),
|
||||
#elif defined(CONFIG_X86_32)
|
||||
@ -225,6 +229,9 @@ void __init idt_setup_early_traps(void)
|
||||
void __init idt_setup_traps(void)
|
||||
{
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user