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

x86/fred: Disallow the swapgs instruction when FRED is enabled

SWAPGS is no longer needed thus NOT allowed with FRED because FRED
transitions ensure that an operating system can _always_ operate
with its own GS base address:

- For events that occur in ring 3, FRED event delivery swaps the GS
base address with the IA32_KERNEL_GS_BASE MSR.

- ERETU (the FRED transition that returns to ring 3) also swaps the
GS base address with the IA32_KERNEL_GS_BASE MSR.

And the operating system can still setup the GS segment for a user
thread without the need of loading a user thread GS with:

- Using LKGS, available with FRED, to modify other attributes of the
GS segment without compromising its ability always to operate with
its own GS base address.

- Accessing the GS segment base address for a user thread as before
using RDMSR or WRMSR on the IA32_KERNEL_GS_BASE MSR.

Note, LKGS loads the GS base address into the IA32_KERNEL_GS_BASE MSR
instead of the GS segment's descriptor cache. As such, the operating
system never changes its runtime GS base address.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: Xin Li <xin3.li@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Tested-by: Shan Kang <shan.kang@intel.com>
Link: https://lore.kernel.org/r/20231205105030.8698-19-xin3.li@intel.com

authored by

H. Peter Anvin (Intel) and committed by
Borislav Petkov (AMD)
09794f68 9356c4b8

+25 -2
+25 -2
arch/x86/kernel/process_64.c
··· 166 166 167 167 lockdep_assert_irqs_disabled(); 168 168 169 - if (!cpu_feature_enabled(X86_FEATURE_XENPV)) { 169 + /* 170 + * SWAPGS is no longer needed thus NOT allowed with FRED because 171 + * FRED transitions ensure that an operating system can _always_ 172 + * operate with its own GS base address: 173 + * - For events that occur in ring 3, FRED event delivery swaps 174 + * the GS base address with the IA32_KERNEL_GS_BASE MSR. 175 + * - ERETU (the FRED transition that returns to ring 3) also swaps 176 + * the GS base address with the IA32_KERNEL_GS_BASE MSR. 177 + * 178 + * And the operating system can still setup the GS segment for a 179 + * user thread without the need of loading a user thread GS with: 180 + * - Using LKGS, available with FRED, to modify other attributes 181 + * of the GS segment without compromising its ability always to 182 + * operate with its own GS base address. 183 + * - Accessing the GS segment base address for a user thread as 184 + * before using RDMSR or WRMSR on the IA32_KERNEL_GS_BASE MSR. 185 + * 186 + * Note, LKGS loads the GS base address into the IA32_KERNEL_GS_BASE 187 + * MSR instead of the GS segment’s descriptor cache. As such, the 188 + * operating system never changes its runtime GS base address. 189 + */ 190 + if (!cpu_feature_enabled(X86_FEATURE_FRED) && 191 + !cpu_feature_enabled(X86_FEATURE_XENPV)) { 170 192 native_swapgs(); 171 193 gsbase = rdgsbase(); 172 194 native_swapgs(); ··· 213 191 { 214 192 lockdep_assert_irqs_disabled(); 215 193 216 - if (!cpu_feature_enabled(X86_FEATURE_XENPV)) { 194 + if (!cpu_feature_enabled(X86_FEATURE_FRED) && 195 + !cpu_feature_enabled(X86_FEATURE_XENPV)) { 217 196 native_swapgs(); 218 197 wrgsbase(gsbase); 219 198 native_swapgs();