Re: [PATCH RESEND] x86/speculation: Fix user-mode spectre-v2 protection with KERNEL_IBRS

From: Borislav Petkov
Date: Mon Feb 20 2023 - 09:31:50 EST


Drop stable@.

On Mon, Feb 20, 2023 at 04:34:02AM -0800, KP Singh wrote:
> > > On Mon, Feb 20, 2023 at 01:01:27PM +0100, KP Singh wrote:
> > > > +static inline bool spectre_v2_user_no_stibp(enum spectre_v2_mitigation mode)
> > > > +{
> > > > + /* When IBRS or enhanced IBRS is enabled, STIBP is not needed.
> > > > + *
> > > > + * However, With KERNEL_IBRS, the IBRS bit is cleared on return
> > > > + * to user and the user-mode code needs to be able to enable protection
> > > > + * from cross-thread training, either by always enabling STIBP or
> > > > + * by enabling it via prctl.
> > > > + */
> > > > + return (spectre_v2_in_ibrs_mode(mode) &&
> > > > + !cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS));
> > > > +}
> > >
> > > The comments and code confused me, they both seem to imply some
> > > distinction between IBRS and KERNEL_IBRS, but in the kernel those are
> > > functionally the same thing. e.g., the kernel doesn't have a user IBRS
> > > mode.
> > >
> > > And, unless I'm missing some subtlety here, it seems to be a convoluted
> > > way of saying that eIBRS doesn't need STIBP in user space.
>
> Actually, there is a subtlety, STIBP is not needed in IBRS and eIBRS
> however, with KERNEL_IBRS we only enable IBRS (by setting and
> unsetting the IBRS bit of SPEC_CTL) in the kernel context and this is
> why we need to allow STIBP in userspace. If it were for pure IBRS, we
> would not need it either (based on my reading). Now, with
> spectre_v2_in_ibrs_mode, as per the current implementation implies
> that KERNEL_IBRS is chosen, but this may change. Also, I would also
> prefer to have it more readable in the sense that:
>
> "If the kernel decides to write 0 to the IBRS bit on returning to the
> user, STIBP needs to to be allowed in user space"

From:

https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/indirect-branch-restricted-speculation.html

"If IA32_SPEC_CTRL.IBRS is already 1 before a transition to a more
privileged predictor mode, some processors may allow the predicted
targets of indirect branches executed in that predictor mode to be
controlled by software that executed before the transition. Software can
avoid this by using WRMSR on the IA32_SPEC_CTRL MSR to set the IBRS bit
to 1 after any such transition, regardless of the bit’s previous value.
It is not necessary to clear the bit first; writing it with a value of
1 after the transition suffices, regardless of the bit’s original
value."

I'd love it if we could simplify our code by not caring of the IBRS bit
when returning to user but I'm afraid that it ain't that simple.

This above probably wants to say that you need to write 1 on CPL change
because it has a flushing behavior of killing user prediction entries.

Lemme add Andy and dhansen for clarification.

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette