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

Merge tag 'x86-urgent-2024-05-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull misc x86 fixes from Ingo Molnar:

 - Remove the broken vsyscall emulation code from
   the page fault code

 - Fix kexec crash triggered by certain SEV RMP
   table layouts

 - Fix unchecked MSR access error when disabling
   the x2APIC via iommu=off

* tag 'x86-urgent-2024-05-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mm: Remove broken vsyscall emulation code from the page fault code
  x86/apic: Don't access the APIC when disabling x2APIC
  x86/sev: Add callback to apply RMP table fixups for kexec
  x86/e820: Add a new e820 table update helper
parents 80f8b450 02b670c1
Loading
Loading
Loading
Loading
+2 −26
Original line number Diff line number Diff line
@@ -98,11 +98,6 @@ static int addr_to_vsyscall_nr(unsigned long addr)

static bool write_ok_or_segv(unsigned long ptr, size_t size)
{
	/*
	 * XXX: if access_ok, get_user, and put_user handled
	 * sig_on_uaccess_err, this could go away.
	 */

	if (!access_ok((void __user *)ptr, size)) {
		struct thread_struct *thread = &current->thread;

@@ -120,10 +115,8 @@ 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)
{
	struct task_struct *tsk;
	unsigned long caller;
	int vsyscall_nr, syscall_nr, tmp;
	int prev_sig_on_uaccess_err;
	long ret;
	unsigned long orig_dx;

@@ -172,8 +165,6 @@ bool emulate_vsyscall(unsigned long error_code,
		goto sigsegv;
	}

	tsk = current;

	/*
	 * Check for access_ok violations and find the syscall nr.
	 *
@@ -234,12 +225,8 @@ bool emulate_vsyscall(unsigned long error_code,
		goto do_ret;  /* skip requested */

	/*
	 * With a real vsyscall, page faults cause SIGSEGV.  We want to
	 * preserve that behavior to make writing exploits harder.
	 * With a real vsyscall, page faults cause SIGSEGV.
	 */
	prev_sig_on_uaccess_err = current->thread.sig_on_uaccess_err;
	current->thread.sig_on_uaccess_err = 1;

	ret = -EFAULT;
	switch (vsyscall_nr) {
	case 0:
@@ -262,23 +249,12 @@ bool emulate_vsyscall(unsigned long error_code,
		break;
	}

	current->thread.sig_on_uaccess_err = prev_sig_on_uaccess_err;

check_fault:
	if (ret == -EFAULT) {
		/* Bad news -- userspace fed a bad pointer to a vsyscall. */
		warn_bad_vsyscall(KERN_INFO, regs,
				  "vsyscall fault (exploit attempt?)");

		/*
		 * If we failed to generate a signal for any reason,
		 * generate one here.  (This should be impossible.)
		 */
		if (WARN_ON_ONCE(!sigismember(&tsk->pending.signal, SIGBUS) &&
				 !sigismember(&tsk->pending.signal, SIGSEGV)))
		goto sigsegv;

		return true;  /* Don't emulate the ret. */
	}

	regs->ax = ret;
+1 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type);
extern void e820__range_add   (u64 start, u64 size, enum e820_type type);
extern u64  e820__range_update(u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);
extern u64  e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type);
extern u64  e820__range_update_table(struct e820_table *t, u64 start, u64 size, enum e820_type old_type, enum e820_type new_type);

extern void e820__print_table(char *who);
extern int  e820__update_table(struct e820_table *table);
+0 −1
Original line number Diff line number Diff line
@@ -472,7 +472,6 @@ struct thread_struct {
	unsigned long		iopl_emul;

	unsigned int		iopl_warn:1;
	unsigned int		sig_on_uaccess_err:1;

	/*
	 * Protection Keys Register for Userspace.  Loaded immediately on
+2 −0
Original line number Diff line number Diff line
@@ -269,6 +269,7 @@ int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immut
int rmp_make_shared(u64 pfn, enum pg_level level);
void snp_leak_pages(u64 pfn, unsigned int npages);
void kdump_sev_callback(void);
void snp_fixup_e820_tables(void);
#else
static inline bool snp_probe_rmptable_info(void) { return false; }
static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; }
@@ -282,6 +283,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as
static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; }
static inline void snp_leak_pages(u64 pfn, unsigned int npages) {}
static inline void kdump_sev_callback(void) { }
static inline void snp_fixup_e820_tables(void) {}
#endif

#endif
+11 −5
Original line number Diff line number Diff line
@@ -1771,7 +1771,7 @@ void x2apic_setup(void)
	__x2apic_enable();
}

static __init void apic_set_fixmap(void);
static __init void apic_set_fixmap(bool read_apic);

static __init void x2apic_disable(void)
{
@@ -1793,7 +1793,12 @@ static __init void x2apic_disable(void)
	}

	__x2apic_disable();
	apic_set_fixmap();
	/*
	 * Don't reread the APIC ID as it was already done from
	 * check_x2apic() and the APIC driver still is a x2APIC variant,
	 * which fails to do the read after x2APIC was disabled.
	 */
	apic_set_fixmap(false);
}

static __init void x2apic_enable(void)
@@ -2057,12 +2062,13 @@ void __init init_apic_mappings(void)
	}
}

static __init void apic_set_fixmap(void)
static __init void apic_set_fixmap(bool read_apic)
{
	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
	apic_mmio_base = APIC_BASE;
	apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
		    apic_mmio_base, mp_lapic_addr);
	if (read_apic)
		apic_read_boot_cpu_id(false);
}

@@ -2073,7 +2079,7 @@ void __init register_lapic_address(unsigned long address)
	mp_lapic_addr = address;

	if (!x2apic_mode)
		apic_set_fixmap();
		apic_set_fixmap(true);
}

/*
Loading