Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/fpu: Add members to struct fpu to cache permission information

Dynamically enabled features can be requested by any thread of a running
process at any time. The request does neither enable the feature nor
allocate larger buffers. It just stores the permission to use the feature
by adding the features to the permission bitmap and by calculating the
required sizes for kernel and user space.

The reallocation of the kernel buffer happens when the feature is used
for the first time which is caught by an exception. The permission
bitmap is then checked and if the feature is permitted, then it becomes
fully enabled. If not, the task dies similarly to a task which uses an
undefined instruction.

The size information is precomputed to allow proper sigaltstack size checks
once the feature is permitted, but not yet in use because otherwise this
would open race windows where too small stacks could be installed causing
a later fail on signal delivery.

Initialize them to the default feature set and sizes.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lkml.kernel.org/r/20211021225527.10184-5-chang.seok.bae@intel.com

authored by

Thomas Gleixner and committed by
Borislav Petkov
6f6a7c09 84e4dccc

+51
+46
arch/x86/include/asm/fpu/types.h
··· 352 352 /* @regs is dynamically sized! Don't add anything after @regs! */ 353 353 } __aligned(64); 354 354 355 + struct fpu_state_perm { 356 + /* 357 + * @__state_perm: 358 + * 359 + * This bitmap indicates the permission for state components, which 360 + * are available to a thread group. The permission prctl() sets the 361 + * enabled state bits in thread_group_leader()->thread.fpu. 362 + * 363 + * All run time operations use the per thread information in the 364 + * currently active fpu.fpstate which contains the xfeature masks 365 + * and sizes for kernel and user space. 366 + * 367 + * This master permission field is only to be used when 368 + * task.fpu.fpstate based checks fail to validate whether the task 369 + * is allowed to expand it's xfeatures set which requires to 370 + * allocate a larger sized fpstate buffer. 371 + * 372 + * Do not access this field directly. Use the provided helper 373 + * function. Unlocked access is possible for quick checks. 374 + */ 375 + u64 __state_perm; 376 + 377 + /* 378 + * @__state_size: 379 + * 380 + * The size required for @__state_perm. Only valid to access 381 + * with sighand locked. 382 + */ 383 + unsigned int __state_size; 384 + 385 + /* 386 + * @__user_state_size: 387 + * 388 + * The size required for @__state_perm user part. Only valid to 389 + * access with sighand locked. 390 + */ 391 + unsigned int __user_state_size; 392 + }; 393 + 355 394 /* 356 395 * Highest level per task FPU state data structure that 357 396 * contains the FPU register state plus various FPU ··· 433 394 * used only for KVM support to swap out the regular task fpstate. 434 395 */ 435 396 struct fpstate *__task_fpstate; 397 + 398 + /* 399 + * @perm: 400 + * 401 + * Permission related information 402 + */ 403 + struct fpu_state_perm perm; 436 404 437 405 /* 438 406 * @__fpstate:
+5
arch/x86/kernel/fpu/core.c
··· 412 412 /* Set the fpstate pointer to the default fpstate */ 413 413 fpu->fpstate = &fpu->__fpstate; 414 414 __fpstate_reset(fpu->fpstate); 415 + 416 + /* Initialize the permission related info in fpu */ 417 + fpu->perm.__state_perm = fpu_kernel_cfg.default_features; 418 + fpu->perm.__state_size = fpu_kernel_cfg.default_size; 419 + fpu->perm.__user_state_size = fpu_user_cfg.default_size; 415 420 } 416 421 417 422 /* Clone current's FPU state on fork */