Commit 9f2bb6c7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_cpu_for_7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 cpu updates from Dave Hansen:

 - Complete LASS enabling: deal with vsyscall and EFI

   The existing Linear Address Space Separation (LASS) support punted
   on support for common EFI and vsyscall configs. Complete the
   implementation by supporting EFI and vsyscall=xonly.

 - Clean up CPUID usage in newer Intel "avs" audio driver and update the
   x86-cpuid-db file

* tag 'x86_cpu_for_7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  tools/x86/kcpuid: Update bitfields to x86-cpuid-db v3.0
  ASoC: Intel: avs: Include CPUID header at file scope
  ASoC: Intel: avs: Check maximum valid CPUID leaf
  x86/cpu: Remove LASS restriction on vsyscall emulation
  x86/vsyscall: Disable LASS if vsyscall mode is set to EMULATE
  x86/vsyscall: Restore vsyscall=xonly mode under LASS
  x86/traps: Consolidate user fixups in the #GP handler
  x86/vsyscall: Reorganize the page fault emulation code
  x86/cpu: Remove LASS restriction on EFI
  x86/efi: Disable LASS while executing runtime services
  x86/cpu: Defer LASS enabling until userspace comes up
parents 49b30f3e 124ad303
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -8398,7 +8398,9 @@ Kernel parameters

			emulate     Vsyscalls turn into traps and are emulated
			            reasonably safely.  The vsyscall page is
				    readable.
				    readable.  This disables the Linear
				    Address Space Separation (LASS) security
				    feature and makes the system less secure.

			xonly       [default] Vsyscalls turn into traps and are
			            emulated reasonably safely.  The vsyscall
+56 −35
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
 * soon be no new userspace code that will ever use a vsyscall.
 *
 * The code in this file emulates vsyscalls when notified of a page
 * fault to a vsyscall address.
 * fault or a general protection fault to a vsyscall address.
 */

#include <linux/kernel.h>
@@ -62,6 +62,11 @@ static int __init vsyscall_setup(char *str)
		else
			return -EINVAL;

		if (cpu_feature_enabled(X86_FEATURE_LASS) && vsyscall_mode == EMULATE) {
			setup_clear_cpu_cap(X86_FEATURE_LASS);
			pr_warn_once("x86/cpu: Disabling LASS due to vsyscall=emulate\n");
		}

		return 0;
	}

@@ -111,47 +116,16 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
	}
}

bool emulate_vsyscall(unsigned long error_code,
		      struct pt_regs *regs, unsigned long address)
static bool __emulate_vsyscall(struct pt_regs *regs, unsigned long address)
{
	unsigned long caller;
	int vsyscall_nr, syscall_nr, tmp;
	long ret;
	unsigned long orig_dx;

	/* Write faults or kernel-privilege faults never get fixed up. */
	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
		return false;

	/*
	 * Assume that faults at regs->ip are because of an
	 * instruction fetch. Return early and avoid
	 * emulation for faults during data accesses:
	 */
	if (address != regs->ip) {
		/* Failed vsyscall read */
		if (vsyscall_mode == EMULATE)
			return false;

		/*
		 * User code tried and failed to read the vsyscall page.
		 */
		warn_bad_vsyscall(KERN_INFO, regs, "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
	/* Confirm that the fault happened in 64-bit user mode */
	if (!user_64bit_mode(regs))
		return false;
	}

	/*
	 * X86_PF_INSTR is only set when NX is supported.  When
	 * available, use it to double-check that the emulation code
	 * is only being used for instruction fetches:
	 */
	if (cpu_feature_enabled(X86_FEATURE_NX))
		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));

	/*
	 * No point in checking CS -- the only way to get here is a user mode
	 * trap to a high address, which means that we're in 64-bit user code.
	 */

	if (vsyscall_mode == NONE) {
		warn_bad_vsyscall(KERN_INFO, regs,
@@ -280,6 +254,53 @@ bool emulate_vsyscall(unsigned long error_code,
	return true;
}

bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs,
			 unsigned long address)
{
	/* Write faults or kernel-privilege faults never get fixed up. */
	if ((error_code & (X86_PF_WRITE | X86_PF_USER)) != X86_PF_USER)
		return false;

	/*
	 * Assume that faults at regs->ip are because of an instruction
	 * fetch. Return early and avoid emulation for faults during
	 * data accesses:
	 */
	if (address != regs->ip) {
		/* Failed vsyscall read */
		if (vsyscall_mode == EMULATE)
			return false;

		/* User code tried and failed to read the vsyscall page. */
		warn_bad_vsyscall(KERN_INFO, regs,
				  "vsyscall read attempt denied -- look up the vsyscall kernel parameter if you need a workaround");
		return false;
	}

	/*
	 * X86_PF_INSTR is only set when NX is supported.  When
	 * available, use it to double-check that the emulation code
	 * is only being used for instruction fetches:
	 */
	if (cpu_feature_enabled(X86_FEATURE_NX))
		WARN_ON_ONCE(!(error_code & X86_PF_INSTR));

	return __emulate_vsyscall(regs, address);
}

bool emulate_vsyscall_gp(struct pt_regs *regs)
{
	/* Without LASS, vsyscall accesses are expected to generate a #PF */
	if (!cpu_feature_enabled(X86_FEATURE_LASS))
		return false;

	/* Emulate only if the RIP points to the vsyscall address */
	if (!is_vsyscall_vaddr(regs->ip))
		return false;

	return __emulate_vsyscall(regs, regs->ip);
}

/*
 * A pseudo VMA to allow ptrace access for the vsyscall page.  This only
 * covers the 64bit vsyscall page now. 32bit has a real VMA now and does
+9 −4
Original line number Diff line number Diff line
@@ -14,15 +14,20 @@ extern void set_vsyscall_pgtable_user_bits(pgd_t *root);
 * Called on instruction fetch fault in vsyscall page.
 * Returns true if handled.
 */
extern bool emulate_vsyscall(unsigned long error_code,
			     struct pt_regs *regs, unsigned long address);
bool emulate_vsyscall_pf(unsigned long error_code, struct pt_regs *regs, unsigned long address);
bool emulate_vsyscall_gp(struct pt_regs *regs);
#else
static inline void map_vsyscall(void) {}
static inline bool emulate_vsyscall(unsigned long error_code,
static inline bool emulate_vsyscall_pf(unsigned long error_code,
				       struct pt_regs *regs, unsigned long address)
{
	return false;
}

static inline bool emulate_vsyscall_gp(struct pt_regs *regs)
{
	return false;
}
#endif

/*
+18 −17
Original line number Diff line number Diff line
@@ -409,27 +409,29 @@ static __always_inline void setup_umip(struct cpuinfo_x86 *c)
	cr4_clear_bits(X86_CR4_UMIP);
}

static __always_inline void setup_lass(struct cpuinfo_x86 *c)
static int enable_lass(unsigned int cpu)
{
	if (!cpu_feature_enabled(X86_FEATURE_LASS))
		return;
	cr4_set_bits(X86_CR4_LASS);

	return 0;
}

/*
	 * Legacy vsyscall page access causes a #GP when LASS is active.
	 * Disable LASS because the #GP handler doesn't support vsyscall
	 * emulation.
	 *
	 * Also disable LASS when running under EFI, as some runtime and
	 * boot services rely on 1:1 mappings in the lower half.
 * Finalize features that need to be enabled just before entering
 * userspace. Note that this only runs on a single CPU. Use appropriate
 * callbacks if all the CPUs need to reflect the same change.
 */
	if (IS_ENABLED(CONFIG_X86_VSYSCALL_EMULATION) ||
	    IS_ENABLED(CONFIG_EFI)) {
		setup_clear_cpu_cap(X86_FEATURE_LASS);
		return;
	}
static int cpu_finalize_pre_userspace(void)
{
	if (!cpu_feature_enabled(X86_FEATURE_LASS))
		return 0;

	cr4_set_bits(X86_CR4_LASS);
	/* Runs on all online CPUs and future CPUs that come online. */
	cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/lass:enable", enable_lass, NULL);

	return 0;
}
late_initcall(cpu_finalize_pre_userspace);

/* These bits should not change their value after CPU init is finished. */
static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP |
@@ -2061,7 +2063,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
	setup_smep(c);
	setup_smap(c);
	setup_umip(c);
	setup_lass(c);

	/*
	 * The vendor-specific functions might have changed features.
+7 −5
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@
#include <asm/tdx.h>
#include <asm/cfi.h>
#include <asm/msr.h>
#include <asm/vsyscall.h>

#ifdef CONFIG_X86_64
#include <asm/x86_init.h>
@@ -921,11 +922,6 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)

	cond_local_irq_enable(regs);

	if (static_cpu_has(X86_FEATURE_UMIP)) {
		if (user_mode(regs) && fixup_umip_exception(regs))
			goto exit;
	}

	if (v8086_mode(regs)) {
		local_irq_enable();
		handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
@@ -940,6 +936,12 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
		if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0))
			goto exit;

		if (fixup_umip_exception(regs))
			goto exit;

		if (emulate_vsyscall_gp(regs))
			goto exit;

		gp_user_force_sig_segv(regs, X86_TRAP_GP, error_code, desc);
		goto exit;
	}
Loading