Re: Save a WRMSR GS.base?

From: H. Peter Anvin

Date: Thu Jun 04 2026 - 23:26:08 EST


On June 4, 2026 7:54:53 PM PDT, Borislav Petkov <bp@xxxxxxxxx> wrote:
>On Thu, Jun 04, 2026 at 07:36:01PM -0700, H. Peter Anvin wrote:
>> >diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
>> >index b85e715ebb30..248c39da9ba0 100644
>> >--- a/arch/x86/kernel/process_64.c
>> >+++ b/arch/x86/kernel/process_64.c
>> >@@ -391,16 +391,23 @@ static __always_inline void x86_pkru_load(struct thread_struct *prev,
>> > static __always_inline void x86_fsgsbase_load(struct thread_struct *prev,
>> > struct thread_struct *next)
>> > {
>> >+ bool loaded_gs = false;
>> >+
>> > if (static_cpu_has(X86_FEATURE_FSGSBASE)) {
>> > /* Update the FS and GS selectors if they could have changed. */
>> > if (unlikely(prev->fsindex || next->fsindex))
>> > loadseg(FS, next->fsindex);
>> >- if (unlikely(prev->gsindex || next->gsindex))
>> >+
>> >+ if (unlikely(prev->gsindex || next->gsindex)) {
>> > loadseg(GS, next->gsindex);
>> >+ loaded_gs = true;
>> >+ }
>> >
>> > /* Update the bases. */
>> > wrfsbase(next->fsbase);
>> >- __wrgsbase_inactive(next->gsbase);
>> >+
>> >+ if (!(cpu_feature_enabled(X86_FEATURE_LKGS) && loaded_gs))
>> >+ __wrgsbase_inactive(next->gsbase);
>> > } else {
>> > load_seg_legacy(prev->fsindex, prev->fsbase,
>> > next->fsindex, next->fsbase, FS);
>> >
>> >
>> >Thx.
>> >
>>
>> Also consider that user space might have done:
>>
>> mov gs,...
>> wrgsbase ...
>>
>> So gs.selector > 3 doesn't necessarily mean that the base is consistent with the descriptor.
>
>Right, I want to avoid the second write to KERNEL_GS_BASE iff we have done
>LKGS before.
>

I guess the question is why there is a "first" one.

Logically the sequence should be LKGS first, if needed; then WRMSR(NS). LKGS can be replaced with swapgs/mov gs/swapgs on legacy.