Re: [PATCH] x86: also disable FSRM if ERMS is disabled
From: Daniel Verkamp
Date: Fri Sep 23 2022 - 13:25:41 EST
On Fri, Sep 23, 2022 at 4:13 AM Borislav Petkov <bp@xxxxxxxxx> wrote:
>
> On Thu, Sep 22, 2022 at 05:58:27PM -0700, Daniel Verkamp wrote:
> > In the "Fast Short REP MOVSB" path of memmove, if we take the path where
> > the FSRM flag is enabled but the ERMS flag is not, there is no longer a
> > check for length >= 0x20 (both alternatives will be replaced with NOPs).
> > If a memmove() requiring a forward copy of less than 0x20 bytes happens
> > in this case, the `sub $0x20, %rdx` will cause the length to roll around
> > to a huge value and the copy will eventually hit a page fault.
> >
> > This is not intended to happen, as the comment above the alternatives
> > mentions "FSRM implies ERMS".
> >
> > However, there is a check in early_init_intel() that can disable ERMS,
> > so we should also be disabling FSRM in this path to maintain correctness
> > of the memmove() optimization.
>
> Is this something you hit in a real-world scenario? If so, how exactly?
>
> Thx.
Yes, we hit this in crosvm when booting the guest kernel with either
OVMF or u-boot on an Intel 12th Gen CPU. The guest kernel boots fine
when loaded directly (using the crosvm kernel loader and not running
any firmware setup in the guest), but it crashes when booting with
firmware inside the first forward memmove() after alternatives are set
up (which happens to be in printk). I haven't gotten to the bottom of
why exactly using firmware is causing this to be set up in an
inconsistent way, but this is a real-world situation, not just a
hypothetical.
Now that I look at it with fresh eyes again, maybe we should instead
directly patch the memmove FSRM alternative so that the flag-set
version just does the same jmp as the ERMS one. I can prepare a patch
for that instead of (or in addition to) this one if that sounds
better.
Thanks,
-- Daniel