Commit 0a7c10df authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_urgent_for_v5.12_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:

 - A couple of SEV-ES fixes and robustifications: verify usermode stack
   pointer in NMI is not coming from the syscall gap, correctly track
   IRQ states in the #VC handler and access user insn bytes atomically
   in same handler as latter cannot sleep.

 - Balance 32-bit fast syscall exit path to do the proper work on exit
   and thus not confuse audit and ptrace frameworks.

 - Two fixes for the ORC unwinder going "off the rails" into KASAN
   redzones and when ORC data is missing.

* tag 'x86_urgent_for_v5.12_rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/sev-es: Use __copy_from_user_inatomic()
  x86/sev-es: Correctly track IRQ states in runtime #VC handler
  x86/sev-es: Check regs->sp is trusted before adjusting #VC IST stack
  x86/sev-es: Introduce ip_within_syscall_gap() helper
  x86/entry: Fix entry/exit mismatch on failed fast 32-bit syscalls
  x86/unwind/orc: Silence warnings caused by missing ORC data
  x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2
parents c3c7579f bffe30dd
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -128,7 +128,8 @@ static noinstr bool __do_fast_syscall_32(struct pt_regs *regs)
		regs->ax = -EFAULT;

		instrumentation_end();
		syscall_exit_to_user_mode(regs);
		local_irq_disable();
		irqentry_exit_to_user_mode(regs);
		return false;
	}

+2 −0
Original line number Diff line number Diff line
@@ -210,6 +210,8 @@ SYM_CODE_START(entry_SYSCALL_compat)
	/* Switch to the kernel stack */
	movq	PER_CPU_VAR(cpu_current_top_of_stack), %rsp

SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL)

	/* Construct struct pt_regs on stack */
	pushq	$__USER32_DS		/* pt_regs->ss */
	pushq	%r8			/* pt_regs->sp */
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx);
int insn_get_code_seg_params(struct pt_regs *regs);
int insn_fetch_from_user(struct pt_regs *regs,
			 unsigned char buf[MAX_INSN_SIZE]);
int insn_fetch_from_user_inatomic(struct pt_regs *regs,
				  unsigned char buf[MAX_INSN_SIZE]);
bool insn_decode(struct insn *insn, struct pt_regs *regs,
		 unsigned char buf[MAX_INSN_SIZE], int buf_size);

+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ void __end_SYSENTER_singlestep_region(void);
void entry_SYSENTER_compat(void);
void __end_entry_SYSENTER_compat(void);
void entry_SYSCALL_compat(void);
void entry_SYSCALL_compat_safe_stack(void);
void entry_INT80_compat(void);
#ifdef CONFIG_XEN_PV
void xen_entry_INT80_compat(void);
+15 −0
Original line number Diff line number Diff line
@@ -94,6 +94,8 @@ struct pt_regs {
#include <asm/paravirt_types.h>
#endif

#include <asm/proto.h>

struct cpuinfo_x86;
struct task_struct;

@@ -175,6 +177,19 @@ static inline bool any_64bit_mode(struct pt_regs *regs)
#ifdef CONFIG_X86_64
#define current_user_stack_pointer()	current_pt_regs()->sp
#define compat_user_stack_pointer()	current_pt_regs()->sp

static inline bool ip_within_syscall_gap(struct pt_regs *regs)
{
	bool ret = (regs->ip >= (unsigned long)entry_SYSCALL_64 &&
		    regs->ip <  (unsigned long)entry_SYSCALL_64_safe_stack);

#ifdef CONFIG_IA32_EMULATION
	ret = ret || (regs->ip >= (unsigned long)entry_SYSCALL_compat &&
		      regs->ip <  (unsigned long)entry_SYSCALL_compat_safe_stack);
#endif

	return ret;
}
#endif

static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
Loading