Commit d07a0b86 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_urgent_for_v6.9_rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:

 - Fix CPU feature dependencies of GFNI, VAES, and VPCLMULQDQ

 - Print the correct error code when FRED reports a bad event type

 - Add a FRED-specific INT80 handler without the special dances that
   need to happen in the current one

 - Enable the using-the-default-return-thunk-but-you-should-not warning
   only on configs which actually enable those special return thunks

 - Check the proper feature flags when selecting BHI retpoline
   mitigation

* tag 'x86_urgent_for_v6.9_rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/cpufeatures: Fix dependencies for GFNI, VAES, and VPCLMULQDQ
  x86/fred: Fix incorrect error code printout in fred_bad_type()
  x86/fred: Fix INT80 emulation for FRED
  x86/retpolines: Enable the default thunk warning only on relevant configs
  x86/bugs: Fix BHI retpoline check
parents 977b1ef5 9543f6e2
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -255,6 +255,71 @@ __visible noinstr void do_int80_emulation(struct pt_regs *regs)
	instrumentation_end();
	syscall_exit_to_user_mode(regs);
}

#ifdef CONFIG_X86_FRED
/*
 * A FRED-specific INT80 handler is warranted for the follwing reasons:
 *
 * 1) As INT instructions and hardware interrupts are separate event
 *    types, FRED does not preclude the use of vector 0x80 for external
 *    interrupts. As a result, the FRED setup code does not reserve
 *    vector 0x80 and calling int80_is_external() is not merely
 *    suboptimal but actively incorrect: it could cause a system call
 *    to be incorrectly ignored.
 *
 * 2) It is called only for handling vector 0x80 of event type
 *    EVENT_TYPE_SWINT and will never be called to handle any external
 *    interrupt (event type EVENT_TYPE_EXTINT).
 *
 * 3) FRED has separate entry flows depending on if the event came from
 *    user space or kernel space, and because the kernel does not use
 *    INT insns, the FRED kernel entry handler fred_entry_from_kernel()
 *    falls through to fred_bad_type() if the event type is
 *    EVENT_TYPE_SWINT, i.e., INT insns. So if the kernel is handling
 *    an INT insn, it can only be from a user level.
 *
 * 4) int80_emulation() does a CLEAR_BRANCH_HISTORY. While FRED will
 *    likely take a different approach if it is ever needed: it
 *    probably belongs in either fred_intx()/ fred_other() or
 *    asm_fred_entrypoint_user(), depending on if this ought to be done
 *    for all entries from userspace or only system
 *    calls.
 *
 * 5) INT $0x80 is the fast path for 32-bit system calls under FRED.
 */
DEFINE_FREDENTRY_RAW(int80_emulation)
{
	int nr;

	enter_from_user_mode(regs);

	instrumentation_begin();
	add_random_kstack_offset();

	/*
	 * FRED pushed 0 into regs::orig_ax and regs::ax contains the
	 * syscall number.
	 *
	 * User tracing code (ptrace or signal handlers) might assume
	 * that the regs::orig_ax contains a 32-bit number on invoking
	 * a 32-bit syscall.
	 *
	 * Establish the syscall convention by saving the 32bit truncated
	 * syscall number in regs::orig_ax and by invalidating regs::ax.
	 */
	regs->orig_ax = regs->ax & GENMASK(31, 0);
	regs->ax = -ENOSYS;

	nr = syscall_32_enter(regs);

	local_irq_enable();
	nr = syscall_enter_from_user_mode_work(regs, nr);
	do_syscall_32_irqs_on(regs, nr);

	instrumentation_end();
	syscall_exit_to_user_mode(regs);
}
#endif
#else /* CONFIG_IA32_EMULATION */

/* Handles int $0x80 on a 32bit kernel */
+5 −5
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code
	if (regs->fred_cs.sl > 0) {
		pr_emerg("PANIC: invalid or fatal FRED event; event type %u "
			 "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n",
			 regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax,
			 regs->fred_ss.type, regs->fred_ss.vector, error_code,
			 fred_event_data(regs), regs->cs, regs->ip);
		die("invalid or fatal FRED event", regs, regs->orig_ax);
		die("invalid or fatal FRED event", regs, error_code);
		panic("invalid or fatal FRED event");
	} else {
		unsigned long flags = oops_begin();
@@ -38,10 +38,10 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code

		pr_alert("BUG: invalid or fatal FRED event; event type %u "
			 "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n",
			 regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax,
			 regs->fred_ss.type, regs->fred_ss.vector, error_code,
			 fred_event_data(regs), regs->cs, regs->ip);

		if (__die("Invalid or fatal FRED event", regs, regs->orig_ax))
		if (__die("Invalid or fatal FRED event", regs, error_code))
			sig = 0;

		oops_end(flags, regs, sig);
@@ -66,7 +66,7 @@ static noinstr void fred_intx(struct pt_regs *regs)
	/* INT80 */
	case IA32_SYSCALL_VECTOR:
		if (ia32_enabled())
			return int80_emulation(regs);
			return fred_int80_emulation(regs);
		fallthrough;
#endif

+7 −4
Original line number Diff line number Diff line
@@ -1652,7 +1652,8 @@ static void __init bhi_select_mitigation(void)
		return;

	/* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
	if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
	if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
	    !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
		spec_ctrl_disable_kernel_rrsba();
		if (rrsba_disabled)
			return;
@@ -2808,7 +2809,9 @@ static const char *spectre_bhi_state(void)
		return "; BHI: BHI_DIS_S";
	else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
		return "; BHI: SW loop, KVM: SW loop";
	else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled)
	else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
		 !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) &&
		 rrsba_disabled)
		return "; BHI: Retpoline";
	else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
		return "; BHI: Vulnerable, KVM: SW loop";
+3 −3
Original line number Diff line number Diff line
@@ -44,7 +44,10 @@ static const struct cpuid_dep cpuid_deps[] = {
	{ X86_FEATURE_F16C,			X86_FEATURE_XMM2,     },
	{ X86_FEATURE_AES,			X86_FEATURE_XMM2      },
	{ X86_FEATURE_SHA_NI,			X86_FEATURE_XMM2      },
	{ X86_FEATURE_GFNI,			X86_FEATURE_XMM2      },
	{ X86_FEATURE_FMA,			X86_FEATURE_AVX       },
	{ X86_FEATURE_VAES,			X86_FEATURE_AVX       },
	{ X86_FEATURE_VPCLMULQDQ,		X86_FEATURE_AVX       },
	{ X86_FEATURE_AVX2,			X86_FEATURE_AVX,      },
	{ X86_FEATURE_AVX512F,			X86_FEATURE_AVX,      },
	{ X86_FEATURE_AVX512IFMA,		X86_FEATURE_AVX512F   },
@@ -56,9 +59,6 @@ static const struct cpuid_dep cpuid_deps[] = {
	{ X86_FEATURE_AVX512VL,			X86_FEATURE_AVX512F   },
	{ X86_FEATURE_AVX512VBMI,		X86_FEATURE_AVX512F   },
	{ X86_FEATURE_AVX512_VBMI2,		X86_FEATURE_AVX512VL  },
	{ X86_FEATURE_GFNI,			X86_FEATURE_AVX512VL  },
	{ X86_FEATURE_VAES,			X86_FEATURE_AVX512VL  },
	{ X86_FEATURE_VPCLMULQDQ,		X86_FEATURE_AVX512VL  },
	{ X86_FEATURE_AVX512_VNNI,		X86_FEATURE_AVX512VL  },
	{ X86_FEATURE_AVX512_BITALG,		X86_FEATURE_AVX512VL  },
	{ X86_FEATURE_AVX512_4VNNIW,		X86_FEATURE_AVX512F   },
+7 −0
Original line number Diff line number Diff line
@@ -382,8 +382,15 @@ SYM_FUNC_END(call_depth_return_thunk)
SYM_CODE_START(__x86_return_thunk)
	UNWIND_HINT_FUNC
	ANNOTATE_NOENDBR
#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \
    defined(CONFIG_MITIGATION_SRSO) || \
    defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING)
	ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \
		   "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS
#else
	ANNOTATE_UNRET_SAFE
	ret
#endif
	int3
SYM_CODE_END(__x86_return_thunk)
EXPORT_SYMBOL(__x86_return_thunk)