[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <CALCETrXRvhqw0fibE6qom3sDJ+nOa_aEJQeuAjPofh=8h1Cujg@mail.gmail.com>
Date: Sat, 1 May 2021 09:26:33 -0700
From: Andy Lutomirski <luto@...nel.org>
To: X86 ML <x86@...nel.org>, LKML <linux-kernel@...r.kernel.org>,
David Kaplan <David.Kaplan@....com>,
Andrew Cooper <andrew.cooper3@...rix.com>,
David Woodhouse <dwmw2@...radead.org>,
Josh Poimboeuf <jpoimboe@...hat.com>,
Kees Cook <keescook@...omium.org>, Jann Horn <jannh@...gle.com>
Subject: Do we need to do anything about "dead µops?"
Hi all-
The "I See Dead µops" paper that is all over the Internet right now is
interesting, and I think we should discuss the extent to which we
should do anything about it. I think there are two separate issues:
First, should we (try to) flush the µop cache across privilege
boundaries? I suspect we could find ways to do this, but I don't
really see the point. A sufficiently capable attacker (i.e. one who
can execute their own code in the dangerous speculative window or one
who can find a capable enough string of gadgets) can put secrets into
the TLB, various cache levels, etc. The µop cache is a nice piece of
analysis, but I don't think it's qualitatively different from anything
else that we don't flush. Am I wrong?
Second, the authors claim that their attack works across LFENCE. I
think that this is what's happening:
load secret into %rax
lfence
call/jmp *%rax
As I understand it, on CPUs from all major vendors, the call/jmp will
gladly fetch before lfence retires, but the address from which it
fetches will come from the branch predictors, not from the
speculatively computed value in %rax. So this is nothing new. If the
kernel leaks a secret into the branch predictors, we have already
mostly lost, although we have a degree of protection from the various
flushes we do. In other words, if we do:
load secret into %rax
<-- non-speculative control flow actually gets here
lfence
call/jmp *%rax
then we will train our secret into the predictors but also leak it
into icache, TLB, etc, and we already lose. We shouldn't be doing
this in a way that matters. But, if we do:
mispredicted branch
load secret into %rax
<-- this won't retire because the branch was mispredicted
lfence
<-- here we're fetching but not dispatching
call/jmp *%rax
then the leak does not actually occur unless we already did the
problematic scenario above.
So my tentative analysis is that no action on Linux's part is required.
What do you all think?
--Andy
Powered by blists - more mailing lists