Skip to content

Commit 8363e79

Browse files
committed
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
2 parents b84a7c2 + 28e5e44 commit 8363e79

File tree

5 files changed

+56
-24
lines changed

5 files changed

+56
-24
lines changed

arch/x86/include/asm/fpu/internal.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -578,10 +578,17 @@ static inline void switch_fpu_finish(struct fpu *new_fpu)
578578
* PKRU state is switched eagerly because it needs to be valid before we
579579
* return to userland e.g. for a copy_to_user() operation.
580580
*/
581-
if (current->mm) {
581+
if (!(current->flags & PF_KTHREAD)) {
582+
/*
583+
* If the PKRU bit in xsave.header.xfeatures is not set,
584+
* then the PKRU component was in init state, which means
585+
* XRSTOR will set PKRU to 0. If the bit is not set then
586+
* get_xsave_addr() will return NULL because the PKRU value
587+
* in memory is not valid. This means pkru_val has to be
588+
* set to 0 and not to init_pkru_value.
589+
*/
582590
pk = get_xsave_addr(&new_fpu->state.xsave, XFEATURE_PKRU);
583-
if (pk)
584-
pkru_val = pk->pkru;
591+
pkru_val = pk ? pk->pkru : 0;
585592
}
586593
__write_pkru(pkru_val);
587594
}

arch/x86/kernel/cpu/sgx/virt.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ static int sgx_vepc_release(struct inode *inode, struct file *file)
212212
list_splice_tail(&secs_pages, &zombie_secs_pages);
213213
mutex_unlock(&zombie_secs_pages_lock);
214214

215+
xa_destroy(&vepc->page_array);
215216
kfree(vepc);
216217

217218
return 0;

arch/x86/kernel/fpu/signal.c

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,17 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
307307
return 0;
308308
}
309309

310-
if (!access_ok(buf, size))
311-
return -EACCES;
310+
if (!access_ok(buf, size)) {
311+
ret = -EACCES;
312+
goto out;
313+
}
312314

313-
if (!static_cpu_has(X86_FEATURE_FPU))
314-
return fpregs_soft_set(current, NULL,
315-
0, sizeof(struct user_i387_ia32_struct),
316-
NULL, buf) != 0;
315+
if (!static_cpu_has(X86_FEATURE_FPU)) {
316+
ret = fpregs_soft_set(current, NULL, 0,
317+
sizeof(struct user_i387_ia32_struct),
318+
NULL, buf);
319+
goto out;
320+
}
317321

318322
if (use_xsave()) {
319323
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)
369373
fpregs_unlock();
370374
return 0;
371375
}
376+
377+
/*
378+
* The above did an FPU restore operation, restricted to
379+
* the user portion of the registers, and failed, but the
380+
* microcode might have modified the FPU registers
381+
* nevertheless.
382+
*
383+
* If the FPU registers do not belong to current, then
384+
* invalidate the FPU register state otherwise the task might
385+
* preempt current and return to user space with corrupted
386+
* FPU registers.
387+
*
388+
* In case current owns the FPU registers then no further
389+
* action is required. The fixup below will handle it
390+
* correctly.
391+
*/
392+
if (test_thread_flag(TIF_NEED_FPU_LOAD))
393+
__cpu_invalidate_fpregs_state();
394+
372395
fpregs_unlock();
373396
} else {
374397
/*
@@ -377,7 +400,7 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
377400
*/
378401
ret = __copy_from_user(&env, buf, sizeof(env));
379402
if (ret)
380-
goto err_out;
403+
goto out;
381404
envp = &env;
382405
}
383406

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

408-
if (using_compacted_format()) {
409-
ret = copy_user_to_xstate(&fpu->state.xsave, buf_fx);
410-
} else {
411-
ret = __copy_from_user(&fpu->state.xsave, buf_fx, state_size);
412-
413-
if (!ret && state_size > offsetof(struct xregs_state, header))
414-
ret = validate_user_xstate_header(&fpu->state.xsave.header);
415-
}
431+
ret = copy_user_to_xstate(&fpu->state.xsave, buf_fx);
416432
if (ret)
417-
goto err_out;
433+
goto out;
418434

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

440456
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)
452468
} else {
453469
ret = __copy_from_user(&fpu->state.fsave, buf_fx, state_size);
454470
if (ret)
455-
goto err_out;
471+
goto out;
456472

457473
fpregs_lock();
458474
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)
463479
fpregs_deactivate(fpu);
464480
fpregs_unlock();
465481

466-
err_out:
482+
out:
467483
if (ret)
468484
fpu__clear_user_states(fpu);
469485
return ret;

arch/x86/mm/ioremap.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des
118118
if (!IS_ENABLED(CONFIG_EFI))
119119
return;
120120

121-
if (efi_mem_type(addr) == EFI_RUNTIME_SERVICES_DATA)
121+
if (efi_mem_type(addr) == EFI_RUNTIME_SERVICES_DATA ||
122+
(efi_mem_type(addr) == EFI_BOOT_SERVICES_DATA &&
123+
efi_mem_attributes(addr) & EFI_MEMORY_RUNTIME))
122124
desc->flags |= IORES_MAP_ENCRYPTED;
123125
}
124126

arch/x86/mm/numa.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,13 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
254254

255255
/* make sure all non-reserved blocks are inside the limits */
256256
bi->start = max(bi->start, low);
257-
bi->end = min(bi->end, high);
257+
258+
/* preserve info for non-RAM areas above 'max_pfn': */
259+
if (bi->end > high) {
260+
numa_add_memblk_to(bi->nid, high, bi->end,
261+
&numa_reserved_meminfo);
262+
bi->end = high;
263+
}
258264

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

0 commit comments

Comments
 (0)