Commit 8363e795 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_urgent_for_v5.13_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 fixes from Borislav Petkov:
 "A first set of urgent fixes to the FPU/XSTATE handling mess^W code.
  (There's a lot more in the pipe):

   - Prevent corruption of the XSTATE buffer in signal handling by
     validating what is being copied from userspace first.

   - Invalidate other task's preserved FPU registers on XRSTOR failure
     (#PF) because latter can still modify some of them.

   - Restore the proper PKRU value in case userspace modified it

   - Reset FPU state when signal restoring fails

  Other:

   - Map EFI boot services data memory as encrypted in a SEV guest so
     that the guest can access it and actually boot properly

   - Two SGX correctness fixes: proper resources freeing and a NUMA fix"

* tag 'x86_urgent_for_v5.13_rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/mm: Avoid truncating memblocks for SGX memory
  x86/sgx: Add missing xa_destroy() when virtual EPC is destroyed
  x86/fpu: Reset state for all signal restore failures
  x86/pkru: Write hardware init value to PKRU when xstate is init
  x86/process: Check PF_KTHREAD and not current->mm for kernel threads
  x86/fpu: Invalidate FPU state after a failed XRSTOR from a user buffer
  x86/fpu: Prevent state corruption in __fpu__restore_sig()
  x86/ioremap: Map EFI-reserved memory as encrypted for SEV
parents b84a7c28 28e5e44a
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -578,10 +578,17 @@ static inline void switch_fpu_finish(struct fpu *new_fpu)
	 * PKRU state is switched eagerly because it needs to be valid before we
	 * return to userland e.g. for a copy_to_user() operation.
	 */
	if (current->mm) {
	if (!(current->flags & PF_KTHREAD)) {
		/*
		 * If the PKRU bit in xsave.header.xfeatures is not set,
		 * then the PKRU component was in init state, which means
		 * XRSTOR will set PKRU to 0. If the bit is not set then
		 * get_xsave_addr() will return NULL because the PKRU value
		 * in memory is not valid. This means pkru_val has to be
		 * set to 0 and not to init_pkru_value.
		 */
		pk = get_xsave_addr(&new_fpu->state.xsave, XFEATURE_PKRU);
		if (pk)
			pkru_val = pk->pkru;
		pkru_val = pk ? pk->pkru : 0;
	}
	__write_pkru(pkru_val);
}
+1 −0
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ static int sgx_vepc_release(struct inode *inode, struct file *file)
		list_splice_tail(&secs_pages, &zombie_secs_pages);
	mutex_unlock(&zombie_secs_pages_lock);

	xa_destroy(&vepc->page_array);
	kfree(vepc);

	return 0;
+35 −19
Original line number Diff line number Diff line
@@ -307,13 +307,17 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
		return 0;
	}

	if (!access_ok(buf, size))
		return -EACCES;
	if (!access_ok(buf, size)) {
		ret = -EACCES;
		goto out;
	}

	if (!static_cpu_has(X86_FEATURE_FPU))
		return fpregs_soft_set(current, NULL,
				       0, sizeof(struct user_i387_ia32_struct),
				       NULL, buf) != 0;
	if (!static_cpu_has(X86_FEATURE_FPU)) {
		ret = fpregs_soft_set(current, NULL, 0,
				      sizeof(struct user_i387_ia32_struct),
				      NULL, buf);
		goto out;
	}

	if (use_xsave()) {
		struct _fpx_sw_bytes fx_sw_user;
@@ -369,6 +373,25 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
			fpregs_unlock();
			return 0;
		}

		/*
		 * The above did an FPU restore operation, restricted to
		 * the user portion of the registers, and failed, but the
		 * microcode might have modified the FPU registers
		 * nevertheless.
		 *
		 * If the FPU registers do not belong to current, then
		 * invalidate the FPU register state otherwise the task might
		 * preempt current and return to user space with corrupted
		 * FPU registers.
		 *
		 * In case current owns the FPU registers then no further
		 * action is required. The fixup below will handle it
		 * correctly.
		 */
		if (test_thread_flag(TIF_NEED_FPU_LOAD))
			__cpu_invalidate_fpregs_state();

		fpregs_unlock();
	} else {
		/*
@@ -377,7 +400,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
		 */
		ret = __copy_from_user(&env, buf, sizeof(env));
		if (ret)
			goto err_out;
			goto out;
		envp = &env;
	}

@@ -405,16 +428,9 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
	if (use_xsave() && !fx_only) {
		u64 init_bv = xfeatures_mask_user() & ~user_xfeatures;

		if (using_compacted_format()) {
		ret = copy_user_to_xstate(&fpu->state.xsave, buf_fx);
		} else {
			ret = __copy_from_user(&fpu->state.xsave, buf_fx, state_size);

			if (!ret && state_size > offsetof(struct xregs_state, header))
				ret = validate_user_xstate_header(&fpu->state.xsave.header);
		}
		if (ret)
			goto err_out;
			goto out;

		sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures,
					      fx_only);
@@ -434,7 +450,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
		ret = __copy_from_user(&fpu->state.fxsave, buf_fx, state_size);
		if (ret) {
			ret = -EFAULT;
			goto err_out;
			goto out;
		}

		sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures,
@@ -452,7 +468,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
	} else {
		ret = __copy_from_user(&fpu->state.fsave, buf_fx, state_size);
		if (ret)
			goto err_out;
			goto out;

		fpregs_lock();
		ret = copy_kernel_to_fregs_err(&fpu->state.fsave);
@@ -463,7 +479,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
		fpregs_deactivate(fpu);
	fpregs_unlock();

err_out:
out:
	if (ret)
		fpu__clear_user_states(fpu);
	return ret;
+3 −1
Original line number Diff line number Diff line
@@ -118,7 +118,9 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des
	if (!IS_ENABLED(CONFIG_EFI))
		return;

	if (efi_mem_type(addr) == EFI_RUNTIME_SERVICES_DATA)
	if (efi_mem_type(addr) == EFI_RUNTIME_SERVICES_DATA ||
	    (efi_mem_type(addr) == EFI_BOOT_SERVICES_DATA &&
	     efi_mem_attributes(addr) & EFI_MEMORY_RUNTIME))
		desc->flags |= IORES_MAP_ENCRYPTED;
}

+7 −1
Original line number Diff line number Diff line
@@ -254,7 +254,13 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)

		/* make sure all non-reserved blocks are inside the limits */
		bi->start = max(bi->start, low);
		bi->end = min(bi->end, high);

		/* preserve info for non-RAM areas above 'max_pfn': */
		if (bi->end > high) {
			numa_add_memblk_to(bi->nid, high, bi->end,
					   &numa_reserved_meminfo);
			bi->end = high;
		}

		/* and there's no empty block */
		if (bi->start >= bi->end)