linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Do we need to do anything about "dead µops?"
@ 2021-05-01 16:26 Andy Lutomirski
  2021-05-01 17:35 ` Andrew Cooper
  2021-05-03 23:30 ` Josh Poimboeuf
  0 siblings, 2 replies; 7+ messages in thread
From: Andy Lutomirski @ 2021-05-01 16:26 UTC (permalink / raw)
  To: X86 ML, LKML, David Kaplan, Andrew Cooper, David Woodhouse,
	Josh Poimboeuf, Kees Cook, Jann Horn

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Do we need to do anything about "dead µops?"
  2021-05-01 16:26 Do we need to do anything about "dead µops?" Andy Lutomirski
@ 2021-05-01 17:35 ` Andrew Cooper
  2021-05-03 23:30 ` Josh Poimboeuf
  1 sibling, 0 replies; 7+ messages in thread
From: Andrew Cooper @ 2021-05-01 17:35 UTC (permalink / raw)
  To: Andy Lutomirski, X86 ML, LKML, David Kaplan, David Woodhouse,
	Josh Poimboeuf, Kees Cook, Jann Horn, xen-devel

On 01/05/2021 17:26, Andy Lutomirski wrote:
> 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.

The vendor-provided literature on pipelines (primarily, the optimisation
guides) has the register file down by the execute units, and not near
the frontend.  Letting the frontend have access to the register value is
distinctly non-trivial.

> 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?

Everything here seems to boil down to managing to encode the secret in
the branch predictor state, then managing to recover it via the uop
cache sidechannel.

It is well known and generally understood that once your secret is in
the branch predictor, YHAL.  Code with that property was broken before
this paper, is still broken after this paper, and needs fixing irrespective.

Viewed in these terms, I don't see what security improvement is gained
from trying to flush the uop cache.

I tentatively agree with your conclusion, that no specific action
concerning the uop cache is required.

~Andrew


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Do we need to do anything about "dead µops?"
  2021-05-01 16:26 Do we need to do anything about "dead µops?" Andy Lutomirski
  2021-05-01 17:35 ` Andrew Cooper
@ 2021-05-03 23:30 ` Josh Poimboeuf
  2021-05-04  1:31   ` Andy Lutomirski
  1 sibling, 1 reply; 7+ messages in thread
From: Josh Poimboeuf @ 2021-05-03 23:30 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, LKML, David Kaplan, Andrew Cooper, David Woodhouse,
	Kees Cook, Jann Horn

On Sat, May 01, 2021 at 09:26:33AM -0700, Andy Lutomirski wrote:
> 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?

Wouldn't this type of gadget (half-v1 gadget + value-dependent-branch)
would be much more likely to occur than a traditional Spectre v1
(half-v1 gadget + value-addressed-load)?

Also, in section V.A., they identified 37 gadgets.  Has anybody looked
at those yet?

(And this makes me realize my uaccess pointer masking patch [1] never
got merged...)

[1] https://lore.kernel.org/lkml/1d06ed6485b66b9f674900368b63d7ef79f666ca.1599756789.git.jpoimboe@redhat.com/

-- 
Josh


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Do we need to do anything about "dead µops?"
  2021-05-03 23:30 ` Josh Poimboeuf
@ 2021-05-04  1:31   ` Andy Lutomirski
  2021-05-04  3:16     ` Josh Poimboeuf
  0 siblings, 1 reply; 7+ messages in thread
From: Andy Lutomirski @ 2021-05-04  1:31 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Andy Lutomirski, X86 ML, LKML, David Kaplan, Andrew Cooper,
	David Woodhouse, Kees Cook, Jann Horn

On Mon, May 3, 2021 at 4:30 PM Josh Poimboeuf <jpoimboe@redhat.com> wrote:
>
> On Sat, May 01, 2021 at 09:26:33AM -0700, Andy Lutomirski wrote:
> > 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?
>
> Wouldn't this type of gadget (half-v1 gadget + value-dependent-branch)
> would be much more likely to occur than a traditional Spectre v1
> (half-v1 gadget + value-addressed-load)?

I don't fully believe this.  It's certainly the case that:

if (mispredicted as false)
  return;
secret = some_secret();
if (secret == 42)
  do_something();

will leak the fact that the secret is 42 into the µop cache, but it
will also leak it into the icache and lots of other things.  I see
nothing new here.  That being said, it's probably still worth
investigating the gadgets.

>
> Also, in section V.A., they identified 37 gadgets.  Has anybody looked
> at those yet?

Not I.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Do we need to do anything about "dead µops?"
  2021-05-04  1:31   ` Andy Lutomirski
@ 2021-05-04  3:16     ` Josh Poimboeuf
  2021-05-04 13:06       ` David Laight
  0 siblings, 1 reply; 7+ messages in thread
From: Josh Poimboeuf @ 2021-05-04  3:16 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, LKML, David Kaplan, Andrew Cooper, David Woodhouse,
	Kees Cook, Jann Horn

On Mon, May 03, 2021 at 06:31:21PM -0700, Andy Lutomirski wrote:
> On Mon, May 3, 2021 at 4:30 PM Josh Poimboeuf <jpoimboe@redhat.com> wrote:
> >
> > On Sat, May 01, 2021 at 09:26:33AM -0700, Andy Lutomirski wrote:
> > > 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?
> >
> > Wouldn't this type of gadget (half-v1 gadget + value-dependent-branch)
> > would be much more likely to occur than a traditional Spectre v1
> > (half-v1 gadget + value-addressed-load)?
> 
> I don't fully believe this.  It's certainly the case that:
> 
> if (mispredicted as false)
>   return;
> secret = some_secret();
> if (secret == 42)
>   do_something();

Well, obviously we should never write secret-protecting code in that
manner.

I was actually thinking more along the lines of

	val = 0;

	if (user_supplied_idx < ARRAY_SIZE) // trained to speculatively be 'true'
		val = boring_non_secret_array[user_supplied_idx];

	if (val & 1)
		do_something();

In other words, the victim code wouldn't be accessing the secret
intentionally.  So there's no reason for it to avoid doing
data-dependent branches.

> will leak the fact that the secret is 42 into the µop cache, but it
> will also leak it into the icache and lots of other things.  I see
> nothing new here.

Hm, I suppose.  I don't think I'd ever considered that vector though.

All the more reason to mask usercopy addresses...

-- 
Josh


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: Do we need to do anything about "dead µops?"
  2021-05-04  3:16     ` Josh Poimboeuf
@ 2021-05-04 13:06       ` David Laight
  2021-05-04 13:24         ` Josh Poimboeuf
  0 siblings, 1 reply; 7+ messages in thread
From: David Laight @ 2021-05-04 13:06 UTC (permalink / raw)
  To: 'Josh Poimboeuf', Andy Lutomirski
  Cc: X86 ML, LKML, David Kaplan, Andrew Cooper, David Woodhouse,
	Kees Cook, Jann Horn

From: Josh Poimboeuf
> Sent: 04 May 2021 04:16
...
> I was actually thinking more along the lines of
> 
> 	val = 0;
> 
> 	if (user_supplied_idx < ARRAY_SIZE) // trained to speculatively be 'true'
> 		val = boring_non_secret_array[user_supplied_idx];
> 
> 	if (val & 1)
> 		do_something();
> 
> In other words, the victim code wouldn't be accessing the secret
> intentionally.  So there's no reason for it to avoid doing
> data-dependent branches.

Isn't that one of the very boring standard spectre cases?

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Do we need to do anything about "dead µops?"
  2021-05-04 13:06       ` David Laight
@ 2021-05-04 13:24         ` Josh Poimboeuf
  0 siblings, 0 replies; 7+ messages in thread
From: Josh Poimboeuf @ 2021-05-04 13:24 UTC (permalink / raw)
  To: David Laight
  Cc: Andy Lutomirski, X86 ML, LKML, David Kaplan, Andrew Cooper,
	David Woodhouse, Kees Cook, Jann Horn

On Tue, May 04, 2021 at 01:06:06PM +0000, David Laight wrote:
> From: Josh Poimboeuf
> > Sent: 04 May 2021 04:16
> ...
> > I was actually thinking more along the lines of
> > 
> > 	val = 0;
> > 
> > 	if (user_supplied_idx < ARRAY_SIZE) // trained to speculatively be 'true'
> > 		val = boring_non_secret_array[user_supplied_idx];
> > 
> > 	if (val & 1)
> > 		do_something();
> > 
> > In other words, the victim code wouldn't be accessing the secret
> > intentionally.  So there's no reason for it to avoid doing
> > data-dependent branches.
> 
> Isn't that one of the very boring standard spectre cases?

Classic v1 as described in the Spectre paper was a data-dependent
load/store, not a data-dependent branch.

-- 
Josh


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-05-04 13:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-01 16:26 Do we need to do anything about "dead µops?" Andy Lutomirski
2021-05-01 17:35 ` Andrew Cooper
2021-05-03 23:30 ` Josh Poimboeuf
2021-05-04  1:31   ` Andy Lutomirski
2021-05-04  3:16     ` Josh Poimboeuf
2021-05-04 13:06       ` David Laight
2021-05-04 13:24         ` Josh Poimboeuf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).