Skip to content

Commit d0be2d5

Browse files
committed
Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fpu updates from Ingo Molnar: "Misc changes: - add a pkey sanity check - three commits to improve and future-proof xstate/xfeature handling some more" * 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/pkeys: Add check for pkey "overflow" x86/fpu/xstate: Warn when checking alignment of disabled xfeatures x86/fpu/xstate: Fix XSAVES offsets in setup_xstate_comp() x86/fpu/xstate: Fix last_good_offset in setup_xstate_features()
2 parents fdf5563 + 16171bf commit d0be2d5

File tree

2 files changed

+44
-36
lines changed

2 files changed

+44
-36
lines changed

arch/x86/include/asm/pkeys.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
#define ARCH_DEFAULT_PKEY 0
66

7+
/*
8+
* If more than 16 keys are ever supported, a thorough audit
9+
* will be necessary to ensure that the types that store key
10+
* numbers and masks have sufficient capacity.
11+
*/
712
#define arch_max_pkey() (boot_cpu_has(X86_FEATURE_OSPKE) ? 16 : 1)
813

914
extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,

arch/x86/kernel/fpu/xstate.c

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,6 @@ static bool xfeature_is_supervisor(int xfeature_nr)
120120
return ecx & 1;
121121
}
122122

123-
static bool xfeature_is_user(int xfeature_nr)
124-
{
125-
return !xfeature_is_supervisor(xfeature_nr);
126-
}
127-
128123
/*
129124
* When executing XSAVEOPT (or other optimized XSAVE instructions), if
130125
* a processor implementation detects that an FPU state component is still
@@ -265,21 +260,25 @@ static void __init setup_xstate_features(void)
265260

266261
cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
267262

263+
xstate_sizes[i] = eax;
264+
268265
/*
269-
* If an xfeature is supervisor state, the offset
270-
* in EBX is invalid. We leave it to -1.
266+
* If an xfeature is supervisor state, the offset in EBX is
267+
* invalid, leave it to -1.
271268
*/
272-
if (xfeature_is_user(i))
273-
xstate_offsets[i] = ebx;
269+
if (xfeature_is_supervisor(i))
270+
continue;
271+
272+
xstate_offsets[i] = ebx;
274273

275-
xstate_sizes[i] = eax;
276274
/*
277-
* In our xstate size checks, we assume that the
278-
* highest-numbered xstate feature has the
279-
* highest offset in the buffer. Ensure it does.
275+
* In our xstate size checks, we assume that the highest-numbered
276+
* xstate feature has the highest offset in the buffer. Ensure
277+
* it does.
280278
*/
281279
WARN_ONCE(last_good_offset > xstate_offsets[i],
282-
"x86/fpu: misordered xstate at %d\n", last_good_offset);
280+
"x86/fpu: misordered xstate at %d\n", last_good_offset);
281+
283282
last_good_offset = xstate_offsets[i];
284283
}
285284
}
@@ -326,6 +325,13 @@ static int xfeature_is_aligned(int xfeature_nr)
326325
u32 eax, ebx, ecx, edx;
327326

328327
CHECK_XFEATURE(xfeature_nr);
328+
329+
if (!xfeature_enabled(xfeature_nr)) {
330+
WARN_ONCE(1, "Checking alignment of disabled xfeature %d\n",
331+
xfeature_nr);
332+
return 0;
333+
}
334+
329335
cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
330336
/*
331337
* The value returned by ECX[1] indicates the alignment
@@ -338,11 +344,11 @@ static int xfeature_is_aligned(int xfeature_nr)
338344
/*
339345
* This function sets up offsets and sizes of all extended states in
340346
* xsave area. This supports both standard format and compacted format
341-
* of the xsave aread.
347+
* of the xsave area.
342348
*/
343-
static void __init setup_xstate_comp(void)
349+
static void __init setup_xstate_comp_offsets(void)
344350
{
345-
unsigned int xstate_comp_sizes[XFEATURE_MAX];
351+
unsigned int next_offset;
346352
int i;
347353

348354
/*
@@ -356,31 +362,23 @@ static void __init setup_xstate_comp(void)
356362

357363
if (!boot_cpu_has(X86_FEATURE_XSAVES)) {
358364
for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
359-
if (xfeature_enabled(i)) {
365+
if (xfeature_enabled(i))
360366
xstate_comp_offsets[i] = xstate_offsets[i];
361-
xstate_comp_sizes[i] = xstate_sizes[i];
362-
}
363367
}
364368
return;
365369
}
366370

367-
xstate_comp_offsets[FIRST_EXTENDED_XFEATURE] =
368-
FXSAVE_SIZE + XSAVE_HDR_SIZE;
371+
next_offset = FXSAVE_SIZE + XSAVE_HDR_SIZE;
369372

370373
for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
371-
if (xfeature_enabled(i))
372-
xstate_comp_sizes[i] = xstate_sizes[i];
373-
else
374-
xstate_comp_sizes[i] = 0;
374+
if (!xfeature_enabled(i))
375+
continue;
375376

376-
if (i > FIRST_EXTENDED_XFEATURE) {
377-
xstate_comp_offsets[i] = xstate_comp_offsets[i-1]
378-
+ xstate_comp_sizes[i-1];
377+
if (xfeature_is_aligned(i))
378+
next_offset = ALIGN(next_offset, 64);
379379

380-
if (xfeature_is_aligned(i))
381-
xstate_comp_offsets[i] =
382-
ALIGN(xstate_comp_offsets[i], 64);
383-
}
380+
xstate_comp_offsets[i] = next_offset;
381+
next_offset += xstate_sizes[i];
384382
}
385383
}
386384

@@ -774,7 +772,7 @@ void __init fpu__init_system_xstate(void)
774772

775773
fpu__init_prepare_fx_sw_frame();
776774
setup_init_fpu_buf();
777-
setup_xstate_comp();
775+
setup_xstate_comp_offsets();
778776
print_xstate_offset_size();
779777

780778
pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
@@ -897,8 +895,6 @@ const void *get_xsave_field_ptr(int xfeature_nr)
897895

898896
#ifdef CONFIG_ARCH_HAS_PKEYS
899897

900-
#define NR_VALID_PKRU_BITS (CONFIG_NR_PROTECTION_KEYS * 2)
901-
#define PKRU_VALID_MASK (NR_VALID_PKRU_BITS - 1)
902898
/*
903899
* This will go out and modify PKRU register to set the access
904900
* rights for @pkey to @init_val.
@@ -917,6 +913,13 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
917913
if (!boot_cpu_has(X86_FEATURE_OSPKE))
918914
return -EINVAL;
919915

916+
/*
917+
* This code should only be called with valid 'pkey'
918+
* values originating from in-kernel users. Complain
919+
* if a bad value is observed.
920+
*/
921+
WARN_ON_ONCE(pkey >= arch_max_pkey());
922+
920923
/* Set the bits we need in PKRU: */
921924
if (init_val & PKEY_DISABLE_ACCESS)
922925
new_pkru_bits |= PKRU_AD_BIT;

0 commit comments

Comments
 (0)