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

prctl: Add force disable speculation

For certain use cases it is desired to enforce mitigations so they cannot
be undone afterwards. That's important for loader stubs which want to
prevent a child from disabling the mitigation again. Will also be used for
seccomp(). The extra state preserving of the prctl state for SSB is a
preparatory step for EBPF dymanic speculation control.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

+59 -24
+21 -13
Documentation/userspace-api/spec_ctrl.rst
··· 25 25 ----------------------- 26 26 27 27 PR_GET_SPECULATION_CTRL returns the state of the speculation misfeature 28 - which is selected with arg2 of prctl(2). The return value uses bits 0-2 with 28 + which is selected with arg2 of prctl(2). The return value uses bits 0-3 with 29 29 the following meaning: 30 30 31 - ==== ================ =================================================== 32 - Bit Define Description 33 - ==== ================ =================================================== 34 - 0 PR_SPEC_PRCTL Mitigation can be controlled per task by 35 - PR_SET_SPECULATION_CTRL 36 - 1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is 37 - disabled 38 - 2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is 39 - enabled 40 - ==== ================ =================================================== 31 + ==== ===================== =================================================== 32 + Bit Define Description 33 + ==== ===================== =================================================== 34 + 0 PR_SPEC_PRCTL Mitigation can be controlled per task by 35 + PR_SET_SPECULATION_CTRL 36 + 1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is 37 + disabled 38 + 2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is 39 + enabled 40 + 3 PR_SPEC_FORCE_DISABLE Same as PR_SPEC_DISABLE, but cannot be undone. A 41 + subsequent prctl(..., PR_SPEC_ENABLE) will fail. 42 + ==== ===================== =================================================== 41 43 42 44 If all bits are 0 the CPU is not affected by the speculation misfeature. 43 45 ··· 49 47 50 48 PR_SET_SPECULATION_CTRL 51 49 ----------------------- 50 + 52 51 PR_SET_SPECULATION_CTRL allows to control the speculation misfeature, which 53 52 is selected by arg2 of :manpage:`prctl(2)` per task. arg3 is used to hand 54 - in the control value, i.e. either PR_SPEC_ENABLE or PR_SPEC_DISABLE. 53 + in the control value, i.e. either PR_SPEC_ENABLE or PR_SPEC_DISABLE or 54 + PR_SPEC_FORCE_DISABLE. 55 55 56 56 Common error codes 57 57 ------------------ ··· 74 70 0 Success 75 71 76 72 ERANGE arg3 is incorrect, i.e. it's neither PR_SPEC_ENABLE nor 77 - PR_SPEC_DISABLE 73 + PR_SPEC_DISABLE nor PR_SPEC_FORCE_DISABLE 78 74 79 75 ENXIO Control of the selected speculation misfeature is not possible. 80 76 See PR_GET_SPECULATION_CTRL. 77 + 78 + EPERM Speculation was disabled with PR_SPEC_FORCE_DISABLE and caller 79 + tried to enable it again. 81 80 ======= ================================================================= 82 81 83 82 Speculation misfeature controls ··· 91 84 * prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0); 92 85 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0); 93 86 * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0); 87 + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
+25 -10
arch/x86/kernel/cpu/bugs.c
··· 533 533 534 534 static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl) 535 535 { 536 - bool rds = !!test_tsk_thread_flag(task, TIF_RDS); 536 + bool update; 537 537 538 538 if (ssb_mode != SPEC_STORE_BYPASS_PRCTL) 539 539 return -ENXIO; 540 540 541 - if (ctrl == PR_SPEC_ENABLE) 542 - clear_tsk_thread_flag(task, TIF_RDS); 543 - else 544 - set_tsk_thread_flag(task, TIF_RDS); 541 + switch (ctrl) { 542 + case PR_SPEC_ENABLE: 543 + /* If speculation is force disabled, enable is not allowed */ 544 + if (task_spec_ssb_force_disable(task)) 545 + return -EPERM; 546 + task_clear_spec_ssb_disable(task); 547 + update = test_and_clear_tsk_thread_flag(task, TIF_RDS); 548 + break; 549 + case PR_SPEC_DISABLE: 550 + task_set_spec_ssb_disable(task); 551 + update = !test_and_set_tsk_thread_flag(task, TIF_RDS); 552 + break; 553 + case PR_SPEC_FORCE_DISABLE: 554 + task_set_spec_ssb_disable(task); 555 + task_set_spec_ssb_force_disable(task); 556 + update = !test_and_set_tsk_thread_flag(task, TIF_RDS); 557 + break; 558 + default: 559 + return -ERANGE; 560 + } 545 561 546 562 /* 547 563 * If being set on non-current task, delay setting the CPU 548 564 * mitigation until it is next scheduled. 549 565 */ 550 - if (task == current && rds != !!test_tsk_thread_flag(task, TIF_RDS)) 566 + if (task == current && update) 551 567 speculative_store_bypass_update(); 552 568 553 569 return 0; ··· 575 559 case SPEC_STORE_BYPASS_DISABLE: 576 560 return PR_SPEC_DISABLE; 577 561 case SPEC_STORE_BYPASS_PRCTL: 578 - if (test_tsk_thread_flag(task, TIF_RDS)) 562 + if (task_spec_ssb_force_disable(task)) 563 + return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; 564 + if (task_spec_ssb_disable(task)) 579 565 return PR_SPEC_PRCTL | PR_SPEC_DISABLE; 580 566 return PR_SPEC_PRCTL | PR_SPEC_ENABLE; 581 567 default: ··· 590 572 int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, 591 573 unsigned long ctrl) 592 574 { 593 - if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE) 594 - return -ERANGE; 595 - 596 575 switch (which) { 597 576 case PR_SPEC_STORE_BYPASS: 598 577 return ssb_prctl_set(task, ctrl);
+3
fs/proc/array.c
··· 344 344 case PR_SPEC_NOT_AFFECTED: 345 345 seq_printf(m, "not vulnerable"); 346 346 break; 347 + case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE: 348 + seq_printf(m, "thread force mitigated"); 349 + break; 347 350 case PR_SPEC_PRCTL | PR_SPEC_DISABLE: 348 351 seq_printf(m, "thread mitigated"); 349 352 break;
+9 -1
include/linux/sched.h
··· 1393 1393 #define PFA_NO_NEW_PRIVS 0 /* May not gain new privileges. */ 1394 1394 #define PFA_SPREAD_PAGE 1 /* Spread page cache over cpuset */ 1395 1395 #define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */ 1396 - 1396 + #define PFA_SPEC_SSB_DISABLE 3 /* Speculative Store Bypass disabled */ 1397 + #define PFA_SPEC_SSB_FORCE_DISABLE 4 /* Speculative Store Bypass force disabled*/ 1397 1398 1398 1399 #define TASK_PFA_TEST(name, func) \ 1399 1400 static inline bool task_##func(struct task_struct *p) \ ··· 1418 1417 TASK_PFA_TEST(SPREAD_SLAB, spread_slab) 1419 1418 TASK_PFA_SET(SPREAD_SLAB, spread_slab) 1420 1419 TASK_PFA_CLEAR(SPREAD_SLAB, spread_slab) 1420 + 1421 + TASK_PFA_TEST(SPEC_SSB_DISABLE, spec_ssb_disable) 1422 + TASK_PFA_SET(SPEC_SSB_DISABLE, spec_ssb_disable) 1423 + TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable) 1424 + 1425 + TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) 1426 + TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) 1421 1427 1422 1428 static inline void 1423 1429 current_restore_flags(unsigned long orig_flags, unsigned long flags)
+1
include/uapi/linux/prctl.h
··· 217 217 # define PR_SPEC_PRCTL (1UL << 0) 218 218 # define PR_SPEC_ENABLE (1UL << 1) 219 219 # define PR_SPEC_DISABLE (1UL << 2) 220 + # define PR_SPEC_FORCE_DISABLE (1UL << 3) 220 221 221 222 #endif /* _LINUX_PRCTL_H */