For untrained return thunks to be fully effective, STIBP must be enabled or SMT disabled.
Unified · Split
| @@ -5201,11 +5201,17 @@ · 5200 unmodified lines | ||
| 5201 | 5201 | Speculative Code Execution with Return Instructions) |
| 5202 | 5202 | vulnerability. |
| 5203 | 5203 | |
| 5204 | − off - unconditionally disable | |
| 5205 | − auto - automatically select a migitation | |
| 5206 | − unret - force enable untrained return thunks, | |
| 5207 | − only effective on AMD Zen {1,2} | |
| 5208 | − based systems. | |
| 5204 | + off - no mitigation | |
| 5205 | + auto - automatically select a migitation | |
| 5206 | + auto,nosmt - automatically select a mitigation, | |
| 5207 | + disabling SMT if necessary for | |
| 5208 | + the full mitigation (only on Zen1 | |
| 5209 | + and older without STIBP). | |
| 5210 | + unret - force enable untrained return thunks, | |
| 5211 | + only effective on AMD f15h-f17h | |
| 5212 | + based systems. | |
| 5213 | + unret,nosmt - like unret, will disable SMT when STIBP | |
| 5214 | + is not available. | |
| 5209 | 5215 | |
| 5210 | 5216 | Selecting 'auto' will choose a mitigation method at run |
| 5211 | 5217 | time according to the CPU. |
| @@ -783,19 +783,34 @@ static enum retbleed_mitigation retbleed_mitigation __ro_after_init = · 782 unmodified lines | ||
| 783 | 783 | static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init = |
| 784 | 784 | RETBLEED_CMD_AUTO; |
| 785 | 785 | |
| 786 | +static int __ro_after_init retbleed_nosmt = false; | |
| 787 | + | |
| 786 | 788 | static int __init retbleed_parse_cmdline(char *str) |
| 787 | 789 | { |
| 788 | 790 | if (!str) |
| 789 | 791 | return -EINVAL; |
| 790 | 792 | |
| 791 | − if (!strcmp(str, "off")) | |
| 792 | − retbleed_cmd = RETBLEED_CMD_OFF; | |
| 793 | − else if (!strcmp(str, "auto")) | |
| 794 | − retbleed_cmd = RETBLEED_CMD_AUTO; | |
| 795 | − else if (!strcmp(str, "unret")) | |
| 796 | − retbleed_cmd = RETBLEED_CMD_UNRET; | |
| 797 | − else | |
| 798 | − pr_err("Unknown retbleed option (%s). Defaulting to 'auto'\n", str); | |
| 793 | + while (str) { | |
| 794 | + char *next = strchr(str, ','); | |
| 795 | + if (next) { | |
| 796 | + *next = 0; | |
| 797 | + next++; | |
| 798 | + } | |
| 799 | + | |
| 800 | + if (!strcmp(str, "off")) { | |
| 801 | + retbleed_cmd = RETBLEED_CMD_OFF; | |
| 802 | + } else if (!strcmp(str, "auto")) { | |
| 803 | + retbleed_cmd = RETBLEED_CMD_AUTO; | |
| 804 | + } else if (!strcmp(str, "unret")) { | |
| 805 | + retbleed_cmd = RETBLEED_CMD_UNRET; | |
| 806 | + } else if (!strcmp(str, "nosmt")) { | |
| 807 | + retbleed_nosmt = true; | |
| 808 | + } else { | |
| 809 | + pr_err("Ignoring unknown retbleed option (%s).", str); | |
| 810 | + } | |
| 811 | + | |
| 812 | + str = next; | |
| 813 | + } | |
| 799 | 814 | |
| 800 | 815 | return 0; |
| 801 | 816 | } |
| @@ -841,6 +856,10 @@ static void __init retbleed_select_mitigation(void) · 39 unmodified lines | ||
| 841 | 856 | setup_force_cpu_cap(X86_FEATURE_RETHUNK); |
| 842 | 857 | setup_force_cpu_cap(X86_FEATURE_UNRET); |
| 843 | 858 | |
| 859 | + if (!boot_cpu_has(X86_FEATURE_STIBP) && | |
| 860 | + (retbleed_nosmt || cpu_mitigations_auto_nosmt())) | |
| 861 | + cpu_smt_disable(false); | |
| 862 | + | |
| 844 | 863 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && |
| 845 | 864 | boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) |
| 846 | 865 | pr_err(RETBLEED_UNTRAIN_MSG); |
| @@ -1087,6 +1106,13 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) · 240 unmodified lines | ||
| 1087 | 1106 | boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON)) |
| 1088 | 1107 | mode = SPECTRE_V2_USER_STRICT_PREFERRED; |
| 1089 | 1108 | |
| 1109 | + if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET) { | |
| 1110 | + if (mode != SPECTRE_V2_USER_STRICT && | |
| 1111 | + mode != SPECTRE_V2_USER_STRICT_PREFERRED) | |
| 1112 | + pr_info("Selecting STIBP always-on mode to complement retbleed mitigation'\n"); | |
| 1113 | + mode = SPECTRE_V2_USER_STRICT_PREFERRED; | |
| 1114 | + } | |
| 1115 | + | |
| 1090 | 1116 | spectre_v2_user_stibp = mode; |
| 1091 | 1117 | |
| 1092 | 1118 | set_mode: |
| @@ -2097,10 +2123,18 @@ static ssize_t srbds_show_state(char *buf) · 1004 unmodified lines | ||
| 2097 | 2123 | |
| 2098 | 2124 | static ssize_t retbleed_show_state(char *buf) |
| 2099 | 2125 | { |
| 2100 | − if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET && | |
| 2101 | − (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && | |
| 2102 | − boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)) | |
| 2103 | − return sprintf(buf, "Vulnerable: untrained return thunk on non-Zen uarch\n"); | |
| 2126 | + if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET) { | |
| 2127 | + if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && | |
| 2128 | + boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) | |
| 2129 | + return sprintf(buf, "Vulnerable: untrained return thunk on non-Zen uarch\n"); | |
| 2130 | + | |
| 2131 | + return sprintf(buf, "%s; SMT %s\n", | |
| 2132 | + retbleed_strings[retbleed_mitigation], | |
| 2133 | + !sched_smt_active() ? "disabled" : | |
| 2134 | + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || | |
| 2135 | + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ? | |
| 2136 | + "enabled with STIBP protection" : "vulnerable"); | |
| 2137 | + } | |
| 2104 | 2138 | |
| 2105 | 2139 | return sprintf(buf, "%s\n", retbleed_strings[retbleed_mitigation]); |
| 2106 | 2140 | } |