Commit 015b3155 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86-urgent-2020-09-06' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Ingo Molnar:

 - more generic entry code ABI fallout

 - debug register handling bugfixes

 - fix vmalloc mappings on 32-bit kernels

 - kprobes instrumentation output fix on 32-bit kernels

 - fix over-eager WARN_ON_ONCE() on !SMAP hardware

 - NUMA debugging fix

 - fix Clang related crash on !RETPOLINE kernels

* tag 'x86-urgent-2020-09-06' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/entry: Unbreak 32bit fast syscall
  x86/debug: Allow a single level of #DB recursion
  x86/entry: Fix AC assertion
  tracing/kprobes, x86/ptrace: Fix regs argument order for i386
  x86, fakenuma: Fix invalid starting node ID
  x86/mm/32: Bring back vmalloc faulting on x86_32
  x86/cmdline: Disable jump tables for cmdline.c
parents 68beef57 4facb95b
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -60,16 +60,10 @@ __visible noinstr void do_syscall_64(unsigned long nr, struct pt_regs *regs)
#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION)
static __always_inline unsigned int syscall_32_enter(struct pt_regs *regs)
{
	unsigned int nr = (unsigned int)regs->orig_ax;

	if (IS_ENABLED(CONFIG_IA32_EMULATION))
		current_thread_info()->status |= TS_COMPAT;
	/*
	 * Subtlety here: if ptrace pokes something larger than 2^32-1 into
	 * orig_ax, the unsigned int return value truncates it.  This may
	 * or may not be necessary, but it matches the old asm behavior.
	 */
	return (unsigned int)syscall_enter_from_user_mode(regs, nr);

	return (unsigned int)regs->orig_ax;
}

/*
@@ -91,6 +85,13 @@ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
{
	unsigned int nr = syscall_32_enter(regs);

	/*
	 * Subtlety here: if ptrace pokes something larger than 2^32-1 into
	 * orig_ax, the unsigned int return value truncates it.  This may
	 * or may not be necessary, but it matches the old asm behavior.
	 */
	nr = (unsigned int)syscall_enter_from_user_mode(regs, nr);

	do_syscall_32_irqs_on(regs, nr);
	syscall_exit_to_user_mode(regs);
}
@@ -100,6 +101,13 @@ static noinstr bool __do_fast_syscall_32(struct pt_regs *regs)
	unsigned int nr = syscall_32_enter(regs);
	int res;

	/*
	 * This cannot use syscall_enter_from_user_mode() as it has to
	 * fetch EBP before invoking any of the syscall entry work
	 * functions.
	 */
	syscall_enter_from_user_mode_prepare(regs);

	instrumentation_begin();
	/* Fetch EBP from where the vDSO stashed it. */
	if (IS_ENABLED(CONFIG_X86_64)) {
@@ -122,6 +130,9 @@ static noinstr bool __do_fast_syscall_32(struct pt_regs *regs)
		return false;
	}

	/* The case truncates any ptrace induced syscall nr > 2^32 -1 */
	nr = (unsigned int)syscall_enter_from_user_mode_work(regs, nr);

	/* Now this is just like a normal syscall. */
	do_syscall_32_irqs_on(regs, nr);
	syscall_exit_to_user_mode(regs);
+10 −2
Original line number Diff line number Diff line
@@ -18,8 +18,16 @@ static __always_inline void arch_check_user_regs(struct pt_regs *regs)
		 * state, not the interrupt state as imagined by Xen.
		 */
		unsigned long flags = native_save_fl();
		WARN_ON_ONCE(flags & (X86_EFLAGS_AC | X86_EFLAGS_DF |
				      X86_EFLAGS_NT));
		unsigned long mask = X86_EFLAGS_DF | X86_EFLAGS_NT;

		/*
		 * For !SMAP hardware we patch out CLAC on entry.
		 */
		if (boot_cpu_has(X86_FEATURE_SMAP) ||
		    (IS_ENABLED(CONFIG_64_BIT) && boot_cpu_has(X86_FEATURE_XENPV)))
			mask |= X86_EFLAGS_AC;

		WARN_ON_ONCE(flags & mask);

		/* We think we came from user mode. Make sure pt_regs agrees. */
		WARN_ON_ONCE(!user_mode(regs));
+1 −1
Original line number Diff line number Diff line
@@ -327,8 +327,8 @@ static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
	static const unsigned int argument_offs[] = {
#ifdef __i386__
		offsetof(struct pt_regs, ax),
		offsetof(struct pt_regs, cx),
		offsetof(struct pt_regs, dx),
		offsetof(struct pt_regs, cx),
#define NR_REG_ARGUMENTS 3
#else
		offsetof(struct pt_regs, di),
+31 −34
Original line number Diff line number Diff line
@@ -729,20 +729,9 @@ static bool is_sysenter_singlestep(struct pt_regs *regs)
#endif
}

static __always_inline void debug_enter(unsigned long *dr6, unsigned long *dr7)
static __always_inline unsigned long debug_read_clear_dr6(void)
{
	/*
	 * Disable breakpoints during exception handling; recursive exceptions
	 * are exceedingly 'fun'.
	 *
	 * Since this function is NOKPROBE, and that also applies to
	 * HW_BREAKPOINT_X, we can't hit a breakpoint before this (XXX except a
	 * HW_BREAKPOINT_W on our stack)
	 *
	 * Entry text is excluded for HW_BP_X and cpu_entry_area, which
	 * includes the entry stack is excluded for everything.
	 */
	*dr7 = local_db_save();
	unsigned long dr6;

	/*
	 * The Intel SDM says:
@@ -755,15 +744,12 @@ static __always_inline void debug_enter(unsigned long *dr6, unsigned long *dr7)
	 *
	 * Keep it simple: clear DR6 immediately.
	 */
	get_debugreg(*dr6, 6);
	get_debugreg(dr6, 6);
	set_debugreg(0, 6);
	/* Filter out all the reserved bits which are preset to 1 */
	*dr6 &= ~DR6_RESERVED;
}
	dr6 &= ~DR6_RESERVED;

static __always_inline void debug_exit(unsigned long dr7)
{
	local_db_restore(dr7);
	return dr6;
}

/*
@@ -863,6 +849,18 @@ out:
static __always_inline void exc_debug_kernel(struct pt_regs *regs,
					     unsigned long dr6)
{
	/*
	 * Disable breakpoints during exception handling; recursive exceptions
	 * are exceedingly 'fun'.
	 *
	 * Since this function is NOKPROBE, and that also applies to
	 * HW_BREAKPOINT_X, we can't hit a breakpoint before this (XXX except a
	 * HW_BREAKPOINT_W on our stack)
	 *
	 * Entry text is excluded for HW_BP_X and cpu_entry_area, which
	 * includes the entry stack is excluded for everything.
	 */
	unsigned long dr7 = local_db_save();
	bool irq_state = idtentry_enter_nmi(regs);
	instrumentation_begin();

@@ -883,6 +881,8 @@ static __always_inline void exc_debug_kernel(struct pt_regs *regs,

	instrumentation_end();
	idtentry_exit_nmi(regs, irq_state);

	local_db_restore(dr7);
}

static __always_inline void exc_debug_user(struct pt_regs *regs,
@@ -894,6 +894,15 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
	 */
	WARN_ON_ONCE(!user_mode(regs));

	/*
	 * NB: We can't easily clear DR7 here because
	 * idtentry_exit_to_usermode() can invoke ptrace, schedule, access
	 * user memory, etc.  This means that a recursive #DB is possible.  If
	 * this happens, that #DB will hit exc_debug_kernel() and clear DR7.
	 * Since we're not on the IST stack right now, everything will be
	 * fine.
	 */

	irqentry_enter_from_user_mode(regs);
	instrumentation_begin();

@@ -907,36 +916,24 @@ static __always_inline void exc_debug_user(struct pt_regs *regs,
/* IST stack entry */
DEFINE_IDTENTRY_DEBUG(exc_debug)
{
	unsigned long dr6, dr7;

	debug_enter(&dr6, &dr7);
	exc_debug_kernel(regs, dr6);
	debug_exit(dr7);
	exc_debug_kernel(regs, debug_read_clear_dr6());
}

/* User entry, runs on regular task stack */
DEFINE_IDTENTRY_DEBUG_USER(exc_debug)
{
	unsigned long dr6, dr7;

	debug_enter(&dr6, &dr7);
	exc_debug_user(regs, dr6);
	debug_exit(dr7);
	exc_debug_user(regs, debug_read_clear_dr6());
}
#else
/* 32 bit does not have separate entry points. */
DEFINE_IDTENTRY_RAW(exc_debug)
{
	unsigned long dr6, dr7;

	debug_enter(&dr6, &dr7);
	unsigned long dr6 = debug_read_clear_dr6();

	if (user_mode(regs))
		exc_debug_user(regs, dr6);
	else
		exc_debug_kernel(regs, dr6);

	debug_exit(dr7);
}
#endif

+1 −1
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_cmdline.o = -pg
endif

CFLAGS_cmdline.o := -fno-stack-protector
CFLAGS_cmdline.o := -fno-stack-protector -fno-jump-tables
endif

inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk
Loading