Skip to content

Commit 1423e26

Browse files
committed
Merge tag 'x86-fpu-2021-07-07' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fpu updates from Thomas Gleixner: "Fixes and improvements for FPU handling on x86: - Prevent sigaltstack out of bounds writes. The kernel unconditionally writes the FPU state to the alternate stack without checking whether the stack is large enough to accomodate it. Check the alternate stack size before doing so and in case it's too small force a SIGSEGV instead of silently corrupting user space data. - MINSIGSTKZ and SIGSTKSZ are constants in signal.h and have never been updated despite the fact that the FPU state which is stored on the signal stack has grown over time which causes trouble in the field when AVX512 is available on a CPU. The kernel does not expose the minimum requirements for the alternate stack size depending on the available and enabled CPU features. ARM already added an aux vector AT_MINSIGSTKSZ for the same reason. Add it to x86 as well. - A major cleanup of the x86 FPU code. The recent discoveries of XSTATE related issues unearthed quite some inconsistencies, duplicated code and other issues. The fine granular overhaul addresses this, makes the code more robust and maintainable, which allows to integrate upcoming XSTATE related features in sane ways" * tag 'x86-fpu-2021-07-07' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (74 commits) x86/fpu/xstate: Clear xstate header in copy_xstate_to_uabi_buf() again x86/fpu/signal: Let xrstor handle the features to init x86/fpu/signal: Handle #PF in the direct restore path x86/fpu: Return proper error codes from user access functions x86/fpu/signal: Split out the direct restore code x86/fpu/signal: Sanitize copy_user_to_fpregs_zeroing() x86/fpu/signal: Sanitize the xstate check on sigframe x86/fpu/signal: Remove the legacy alignment check x86/fpu/signal: Move initial checks into fpu__restore_sig() x86/fpu: Mark init_fpstate __ro_after_init x86/pkru: Remove xstate fiddling from write_pkru() x86/fpu: Don't store PKRU in xstate in fpu_reset_fpstate() x86/fpu: Remove PKRU handling from switch_fpu_finish() x86/fpu: Mask PKRU from kernel XRSTOR[S] operations x86/fpu: Hook up PKRU into ptrace() x86/fpu: Add PKRU storage outside of task XSAVE buffer x86/fpu: Dont restore PKRU in fpregs_restore_userspace() x86/fpu: Rename xfeatures_mask_user() to xfeatures_mask_uabi() x86/fpu: Move FXSAVE_LEAK quirk info __copy_kernel_to_fpregs() x86/fpu: Rename __fpregs_load_activate() to fpregs_restore_userregs() ...
2 parents 4ea9031 + 93c2cdc commit 1423e26

File tree

39 files changed

+1480
-1187
lines changed

39 files changed

+1480
-1187
lines changed

Documentation/x86/elf_auxvec.rst

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
==================================
4+
x86-specific ELF Auxiliary Vectors
5+
==================================
6+
7+
This document describes the semantics of the x86 auxiliary vectors.
8+
9+
Introduction
10+
============
11+
12+
ELF Auxiliary vectors enable the kernel to efficiently provide
13+
configuration-specific parameters to userspace. In this example, a program
14+
allocates an alternate stack based on the kernel-provided size::
15+
16+
#include <sys/auxv.h>
17+
#include <elf.h>
18+
#include <signal.h>
19+
#include <stdlib.h>
20+
#include <assert.h>
21+
#include <err.h>
22+
23+
#ifndef AT_MINSIGSTKSZ
24+
#define AT_MINSIGSTKSZ 51
25+
#endif
26+
27+
....
28+
stack_t ss;
29+
30+
ss.ss_sp = malloc(ss.ss_size);
31+
assert(ss.ss_sp);
32+
33+
ss.ss_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ;
34+
ss.ss_flags = 0;
35+
36+
if (sigaltstack(&ss, NULL))
37+
err(1, "sigaltstack");
38+
39+
40+
The exposed auxiliary vectors
41+
=============================
42+
43+
AT_SYSINFO is used for locating the vsyscall entry point. It is not
44+
exported on 64-bit mode.
45+
46+
AT_SYSINFO_EHDR is the start address of the page containing the vDSO.
47+
48+
AT_MINSIGSTKSZ denotes the minimum stack size required by the kernel to
49+
deliver a signal to user-space. AT_MINSIGSTKSZ comprehends the space
50+
consumed by the kernel to accommodate the user context for the current
51+
hardware configuration. It does not comprehend subsequent user-space stack
52+
consumption, which must be added by the user. (e.g. Above, user-space adds
53+
SIGSTKSZ to AT_MINSIGSTKSZ.)

Documentation/x86/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ x86-specific Documentation
3636
sva
3737
sgx
3838
features
39+
elf_auxvec

arch/x86/events/intel/lbr.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ static void intel_pmu_arch_lbr_xrstors(void *ctx)
491491
{
492492
struct x86_perf_task_context_arch_lbr_xsave *task_ctx = ctx;
493493

494-
copy_kernel_to_dynamic_supervisor(&task_ctx->xsave, XFEATURE_MASK_LBR);
494+
xrstors(&task_ctx->xsave, XFEATURE_MASK_LBR);
495495
}
496496

497497
static __always_inline bool lbr_is_reset_in_cstate(void *ctx)
@@ -576,7 +576,7 @@ static void intel_pmu_arch_lbr_xsaves(void *ctx)
576576
{
577577
struct x86_perf_task_context_arch_lbr_xsave *task_ctx = ctx;
578578

579-
copy_dynamic_supervisor_to_kernel(&task_ctx->xsave, XFEATURE_MASK_LBR);
579+
xsaves(&task_ctx->xsave, XFEATURE_MASK_LBR);
580580
}
581581

582582
static void __intel_pmu_lbr_save(void *ctx)
@@ -993,7 +993,7 @@ static void intel_pmu_arch_lbr_read_xsave(struct cpu_hw_events *cpuc)
993993
intel_pmu_store_lbr(cpuc, NULL);
994994
return;
995995
}
996-
copy_dynamic_supervisor_to_kernel(&xsave->xsave, XFEATURE_MASK_LBR);
996+
xsaves(&xsave->xsave, XFEATURE_MASK_LBR);
997997

998998
intel_pmu_store_lbr(cpuc, xsave->lbr.entries);
999999
}

arch/x86/include/asm/elf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ do { \
312312
NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \
313313
NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \
314314
} \
315+
NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \
315316
} while (0)
316317

317318
/*
@@ -328,6 +329,7 @@ extern unsigned long task_size_32bit(void);
328329
extern unsigned long task_size_64bit(int full_addr_space);
329330
extern unsigned long get_mmap_base(int is_legacy);
330331
extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len);
332+
extern unsigned long get_sigframe_size(void);
331333

332334
#ifdef CONFIG_X86_32
333335

@@ -349,6 +351,7 @@ do { \
349351
if (vdso64_enabled) \
350352
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
351353
(unsigned long __force)current->mm->context.vdso); \
354+
NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \
352355
} while (0)
353356

354357
/* As a historical oddity, the x32 and x86_64 vDSOs are controlled together. */
@@ -357,6 +360,7 @@ do { \
357360
if (vdso64_enabled) \
358361
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
359362
(unsigned long __force)current->mm->context.vdso); \
363+
NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \
360364
} while (0)
361365

362366
#define AT_SYSINFO 32

0 commit comments

Comments
 (0)