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

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
...@@ -578,10 +578,17 @@ static inline void switch_fpu_finish(struct fpu *new_fpu) ...@@ -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 * PKRU state is switched eagerly because it needs to be valid before we
* return to userland e.g. for a copy_to_user() operation. * 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); pk = get_xsave_addr(&new_fpu->state.xsave, XFEATURE_PKRU);
if (pk) pkru_val = pk ? pk->pkru : 0;
pkru_val = pk->pkru;
} }
__write_pkru(pkru_val); __write_pkru(pkru_val);
} }
......
...@@ -212,6 +212,7 @@ static int sgx_vepc_release(struct inode *inode, struct file *file) ...@@ -212,6 +212,7 @@ static int sgx_vepc_release(struct inode *inode, struct file *file)
list_splice_tail(&secs_pages, &zombie_secs_pages); list_splice_tail(&secs_pages, &zombie_secs_pages);
mutex_unlock(&zombie_secs_pages_lock); mutex_unlock(&zombie_secs_pages_lock);
xa_destroy(&vepc->page_array);
kfree(vepc); kfree(vepc);
return 0; return 0;
......
...@@ -307,13 +307,17 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) ...@@ -307,13 +307,17 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
return 0; return 0;
} }
if (!access_ok(buf, size)) if (!access_ok(buf, size)) {
return -EACCES; ret = -EACCES;
goto out;
}
if (!static_cpu_has(X86_FEATURE_FPU)) if (!static_cpu_has(X86_FEATURE_FPU)) {
return fpregs_soft_set(current, NULL, ret = fpregs_soft_set(current, NULL, 0,
0, sizeof(struct user_i387_ia32_struct), sizeof(struct user_i387_ia32_struct),
NULL, buf) != 0; NULL, buf);
goto out;
}
if (use_xsave()) { if (use_xsave()) {
struct _fpx_sw_bytes fx_sw_user; 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) ...@@ -369,6 +373,25 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
fpregs_unlock(); fpregs_unlock();
return 0; 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(); fpregs_unlock();
} else { } else {
/* /*
...@@ -377,7 +400,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) ...@@ -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)); ret = __copy_from_user(&env, buf, sizeof(env));
if (ret) if (ret)
goto err_out; goto out;
envp = &env; envp = &env;
} }
...@@ -405,16 +428,9 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) ...@@ -405,16 +428,9 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
if (use_xsave() && !fx_only) { if (use_xsave() && !fx_only) {
u64 init_bv = xfeatures_mask_user() & ~user_xfeatures; u64 init_bv = xfeatures_mask_user() & ~user_xfeatures;
if (using_compacted_format()) {
ret = copy_user_to_xstate(&fpu->state.xsave, buf_fx); 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) if (ret)
goto err_out; goto out;
sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures, sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures,
fx_only); fx_only);
...@@ -434,7 +450,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size) ...@@ -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); ret = __copy_from_user(&fpu->state.fxsave, buf_fx, state_size);
if (ret) { if (ret) {
ret = -EFAULT; ret = -EFAULT;
goto err_out; goto out;
} }
sanitize_restored_user_xstate(&fpu->state, envp, user_xfeatures, 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) ...@@ -452,7 +468,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
} else { } else {
ret = __copy_from_user(&fpu->state.fsave, buf_fx, state_size); ret = __copy_from_user(&fpu->state.fsave, buf_fx, state_size);
if (ret) if (ret)
goto err_out; goto out;
fpregs_lock(); fpregs_lock();
ret = copy_kernel_to_fregs_err(&fpu->state.fsave); 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) ...@@ -463,7 +479,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
fpregs_deactivate(fpu); fpregs_deactivate(fpu);
fpregs_unlock(); fpregs_unlock();
err_out: out:
if (ret) if (ret)
fpu__clear_user_states(fpu); fpu__clear_user_states(fpu);
return ret; return ret;
......
...@@ -118,7 +118,9 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des ...@@ -118,7 +118,9 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des
if (!IS_ENABLED(CONFIG_EFI)) if (!IS_ENABLED(CONFIG_EFI))
return; 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; desc->flags |= IORES_MAP_ENCRYPTED;
} }
......
...@@ -254,7 +254,13 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi) ...@@ -254,7 +254,13 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
/* make sure all non-reserved blocks are inside the limits */ /* make sure all non-reserved blocks are inside the limits */
bi->start = max(bi->start, low); 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 */ /* and there's no empty block */
if (bi->start >= bi->end) if (bi->start >= bi->end)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment