diff options
| -rw-r--r-- | Documentation/userspace-api/spec_ctrl.rst | 27 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/bugs.c | 12 | ||||
| -rw-r--r-- | arch/x86/kernel/process.c | 12 | ||||
| -rw-r--r-- | include/linux/sched.h | 5 | ||||
| -rw-r--r-- | include/uapi/linux/prctl.h | 1 | ||||
| -rw-r--r-- | tools/include/uapi/linux/prctl.h | 1 |
6 files changed, 46 insertions, 12 deletions
diff --git a/Documentation/userspace-api/spec_ctrl.rst b/Documentation/userspace-api/spec_ctrl.rst index c4dbe6f7cdae..1129c7550a48 100644 --- a/Documentation/userspace-api/spec_ctrl.rst +++ b/Documentation/userspace-api/spec_ctrl.rst | |||
| @@ -28,18 +28,20 @@ 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-3 with | 28 | which is selected with arg2 of prctl(2). The return value uses bits 0-3 with |
| 29 | the following meaning: | 29 | the following meaning: |
| 30 | 30 | ||
| 31 | ==== ===================== =================================================== | 31 | ==== ====================== ================================================== |
| 32 | Bit Define Description | 32 | Bit Define Description |
| 33 | ==== ===================== =================================================== | 33 | ==== ====================== ================================================== |
| 34 | 0 PR_SPEC_PRCTL Mitigation can be controlled per task by | 34 | 0 PR_SPEC_PRCTL Mitigation can be controlled per task by |
| 35 | PR_SET_SPECULATION_CTRL. | 35 | PR_SET_SPECULATION_CTRL. |
| 36 | 1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is | 36 | 1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is |
| 37 | disabled. | 37 | disabled. |
| 38 | 2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is | 38 | 2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is |
| 39 | enabled. | 39 | enabled. |
| 40 | 3 PR_SPEC_FORCE_DISABLE Same as PR_SPEC_DISABLE, but cannot be undone. A | 40 | 3 PR_SPEC_FORCE_DISABLE Same as PR_SPEC_DISABLE, but cannot be undone. A |
| 41 | subsequent prctl(..., PR_SPEC_ENABLE) will fail. | 41 | subsequent prctl(..., PR_SPEC_ENABLE) will fail. |
| 42 | ==== ===================== =================================================== | 42 | 4 PR_SPEC_DISABLE_NOEXEC Same as PR_SPEC_DISABLE, but the state will be |
| 43 | cleared on :manpage:`execve(2)`. | ||
| 44 | ==== ====================== ================================================== | ||
| 43 | 45 | ||
| 44 | If all bits are 0 the CPU is not affected by the speculation misfeature. | 46 | If all bits are 0 the CPU is not affected by the speculation misfeature. |
| 45 | 47 | ||
| @@ -92,6 +94,7 @@ Speculation misfeature controls | |||
| 92 | * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0); | 94 | * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0); |
| 93 | * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0); | 95 | * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0); |
| 94 | * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0); | 96 | * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0); |
| 97 | * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE_NOEXEC, 0, 0); | ||
| 95 | 98 | ||
| 96 | - PR_SPEC_INDIR_BRANCH: Indirect Branch Speculation in User Processes | 99 | - PR_SPEC_INDIR_BRANCH: Indirect Branch Speculation in User Processes |
| 97 | (Mitigate Spectre V2 style attacks against user processes) | 100 | (Mitigate Spectre V2 style attacks against user processes) |
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 01874d54f4fd..2da82eff0eb4 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c | |||
| @@ -798,15 +798,25 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl) | |||
| 798 | if (task_spec_ssb_force_disable(task)) | 798 | if (task_spec_ssb_force_disable(task)) |
| 799 | return -EPERM; | 799 | return -EPERM; |
| 800 | task_clear_spec_ssb_disable(task); | 800 | task_clear_spec_ssb_disable(task); |
| 801 | task_clear_spec_ssb_noexec(task); | ||
| 801 | task_update_spec_tif(task); | 802 | task_update_spec_tif(task); |
| 802 | break; | 803 | break; |
| 803 | case PR_SPEC_DISABLE: | 804 | case PR_SPEC_DISABLE: |
| 804 | task_set_spec_ssb_disable(task); | 805 | task_set_spec_ssb_disable(task); |
| 806 | task_clear_spec_ssb_noexec(task); | ||
| 805 | task_update_spec_tif(task); | 807 | task_update_spec_tif(task); |
| 806 | break; | 808 | break; |
| 807 | case PR_SPEC_FORCE_DISABLE: | 809 | case PR_SPEC_FORCE_DISABLE: |
| 808 | task_set_spec_ssb_disable(task); | 810 | task_set_spec_ssb_disable(task); |
| 809 | task_set_spec_ssb_force_disable(task); | 811 | task_set_spec_ssb_force_disable(task); |
| 812 | task_clear_spec_ssb_noexec(task); | ||
| 813 | task_update_spec_tif(task); | ||
| 814 | break; | ||
| 815 | case PR_SPEC_DISABLE_NOEXEC: | ||
| 816 | if (task_spec_ssb_force_disable(task)) | ||
| 817 | return -EPERM; | ||
| 818 | task_set_spec_ssb_disable(task); | ||
| 819 | task_set_spec_ssb_noexec(task); | ||
| 810 | task_update_spec_tif(task); | 820 | task_update_spec_tif(task); |
| 811 | break; | 821 | break; |
| 812 | default: | 822 | default: |
| @@ -885,6 +895,8 @@ static int ssb_prctl_get(struct task_struct *task) | |||
| 885 | case SPEC_STORE_BYPASS_PRCTL: | 895 | case SPEC_STORE_BYPASS_PRCTL: |
| 886 | if (task_spec_ssb_force_disable(task)) | 896 | if (task_spec_ssb_force_disable(task)) |
| 887 | return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; | 897 | return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; |
| 898 | if (task_spec_ssb_noexec(task)) | ||
| 899 | return PR_SPEC_PRCTL | PR_SPEC_DISABLE_NOEXEC; | ||
| 888 | if (task_spec_ssb_disable(task)) | 900 | if (task_spec_ssb_disable(task)) |
| 889 | return PR_SPEC_PRCTL | PR_SPEC_DISABLE; | 901 | return PR_SPEC_PRCTL | PR_SPEC_DISABLE; |
| 890 | return PR_SPEC_PRCTL | PR_SPEC_ENABLE; | 902 | return PR_SPEC_PRCTL | PR_SPEC_ENABLE; |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 90ae0ca51083..58ac7be52c7a 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -255,6 +255,18 @@ void arch_setup_new_exec(void) | |||
| 255 | /* If cpuid was previously disabled for this task, re-enable it. */ | 255 | /* If cpuid was previously disabled for this task, re-enable it. */ |
| 256 | if (test_thread_flag(TIF_NOCPUID)) | 256 | if (test_thread_flag(TIF_NOCPUID)) |
| 257 | enable_cpuid(); | 257 | enable_cpuid(); |
| 258 | |||
| 259 | /* | ||
| 260 | * Don't inherit TIF_SSBD across exec boundary when | ||
| 261 | * PR_SPEC_DISABLE_NOEXEC is used. | ||
| 262 | */ | ||
| 263 | if (test_thread_flag(TIF_SSBD) && | ||
| 264 | task_spec_ssb_noexec(current)) { | ||
| 265 | clear_thread_flag(TIF_SSBD); | ||
| 266 | task_clear_spec_ssb_disable(current); | ||
| 267 | task_clear_spec_ssb_noexec(current); | ||
| 268 | speculation_ctrl_update(task_thread_info(current)->flags); | ||
| 269 | } | ||
| 258 | } | 270 | } |
| 259 | 271 | ||
| 260 | static inline void switch_to_bitmap(struct thread_struct *prev, | 272 | static inline void switch_to_bitmap(struct thread_struct *prev, |
diff --git a/include/linux/sched.h b/include/linux/sched.h index f9b43c989577..89ddece0b003 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1453,6 +1453,7 @@ static inline bool is_percpu_thread(void) | |||
| 1453 | #define PFA_SPEC_SSB_FORCE_DISABLE 4 /* Speculative Store Bypass force disabled*/ | 1453 | #define PFA_SPEC_SSB_FORCE_DISABLE 4 /* Speculative Store Bypass force disabled*/ |
| 1454 | #define PFA_SPEC_IB_DISABLE 5 /* Indirect branch speculation restricted */ | 1454 | #define PFA_SPEC_IB_DISABLE 5 /* Indirect branch speculation restricted */ |
| 1455 | #define PFA_SPEC_IB_FORCE_DISABLE 6 /* Indirect branch speculation permanently restricted */ | 1455 | #define PFA_SPEC_IB_FORCE_DISABLE 6 /* Indirect branch speculation permanently restricted */ |
| 1456 | #define PFA_SPEC_SSB_NOEXEC 7 /* Speculative Store Bypass clear on execve() */ | ||
| 1456 | 1457 | ||
| 1457 | #define TASK_PFA_TEST(name, func) \ | 1458 | #define TASK_PFA_TEST(name, func) \ |
| 1458 | static inline bool task_##func(struct task_struct *p) \ | 1459 | static inline bool task_##func(struct task_struct *p) \ |
| @@ -1481,6 +1482,10 @@ TASK_PFA_TEST(SPEC_SSB_DISABLE, spec_ssb_disable) | |||
| 1481 | TASK_PFA_SET(SPEC_SSB_DISABLE, spec_ssb_disable) | 1482 | TASK_PFA_SET(SPEC_SSB_DISABLE, spec_ssb_disable) |
| 1482 | TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable) | 1483 | TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable) |
| 1483 | 1484 | ||
| 1485 | TASK_PFA_TEST(SPEC_SSB_NOEXEC, spec_ssb_noexec) | ||
| 1486 | TASK_PFA_SET(SPEC_SSB_NOEXEC, spec_ssb_noexec) | ||
| 1487 | TASK_PFA_CLEAR(SPEC_SSB_NOEXEC, spec_ssb_noexec) | ||
| 1488 | |||
| 1484 | TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) | 1489 | TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) |
| 1485 | TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) | 1490 | TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable) |
| 1486 | 1491 | ||
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index b4875a93363a..094bb03b9cc2 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h | |||
| @@ -219,6 +219,7 @@ struct prctl_mm_map { | |||
| 219 | # define PR_SPEC_ENABLE (1UL << 1) | 219 | # define PR_SPEC_ENABLE (1UL << 1) |
| 220 | # define PR_SPEC_DISABLE (1UL << 2) | 220 | # define PR_SPEC_DISABLE (1UL << 2) |
| 221 | # define PR_SPEC_FORCE_DISABLE (1UL << 3) | 221 | # define PR_SPEC_FORCE_DISABLE (1UL << 3) |
| 222 | # define PR_SPEC_DISABLE_NOEXEC (1UL << 4) | ||
| 222 | 223 | ||
| 223 | /* Reset arm64 pointer authentication keys */ | 224 | /* Reset arm64 pointer authentication keys */ |
| 224 | #define PR_PAC_RESET_KEYS 54 | 225 | #define PR_PAC_RESET_KEYS 54 |
diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h index b4875a93363a..094bb03b9cc2 100644 --- a/tools/include/uapi/linux/prctl.h +++ b/tools/include/uapi/linux/prctl.h | |||
| @@ -219,6 +219,7 @@ struct prctl_mm_map { | |||
| 219 | # define PR_SPEC_ENABLE (1UL << 1) | 219 | # define PR_SPEC_ENABLE (1UL << 1) |
| 220 | # define PR_SPEC_DISABLE (1UL << 2) | 220 | # define PR_SPEC_DISABLE (1UL << 2) |
| 221 | # define PR_SPEC_FORCE_DISABLE (1UL << 3) | 221 | # define PR_SPEC_FORCE_DISABLE (1UL << 3) |
| 222 | # define PR_SPEC_DISABLE_NOEXEC (1UL << 4) | ||
| 222 | 223 | ||
| 223 | /* Reset arm64 pointer authentication keys */ | 224 | /* Reset arm64 pointer authentication keys */ |
| 224 | #define PR_PAC_RESET_KEYS 54 | 225 | #define PR_PAC_RESET_KEYS 54 |
