[gentoo-user] Re: Spectre-NG

2018-05-10 Thread Ian Zimmerman
On 2018-05-10 14:35, Wol's lists wrote:

> > Code may be "security-sensitive" but buggy.  Is the compiler writer
> > really responsible for guessing what the programmer meant to
> > accomplish with buggy code?
> 
> What do you mean by "buggy"?

Relying on UB, or not telling the compiler the whole truth.  You have a
point in that I should have been more specific.

> So if the compiler can't detect undefined behaviour, how the hell do
> you expect the programmer to?

Number one reason is that UB is at least in part a run-time concept.
Clearly the compiler cannot try all possible inputs to a function and
run a simulation on them.  The programmer _can_ insert guard code at the
calling site to prevent the undefined cases from happening.

A "whole program" compiler (ie. one that analyzes code across source
modules) may be able to detect the _possibility_ of UB.  But if you put
such a compiler to work on the kernel (for example), you can probably
take a short vacation while you await the result ;-)

> Oh - and please explain - what is buggy about wanting the following
> program to compile and actually *do* what the code is asking, rather
> than compiling to a no-op ... and 0x00ff is the address of your
> network adaptor? Do you want THAT to be optimised away "because it
> doesn't do anything"?

> int main () {
> int a, b, c;
> a = 2;
> b = 4;
> c = 6;
> }

> int main () {
> void *a;
> a = 0x00ff;
> *a = 6;
> }

This is actually not UB, but a different problem.  Yes, if I write it
like this, I want it eliminated.  When I want to keep it, I will use
the "volatile" keyword which is in the language precisely for this
purpose.

-- 
Please don't Cc: me privately on mailing lists and Usenet,
if you also post the followup to the list or newsgroup.
To reply privately _only_ on Usenet and on broken lists
which rewrite From, fetch the TXT record for no-use.mooo.com.



[gentoo-user] Re: Spectre-NG

2018-05-10 Thread Martin Vaeth
Rich Freeman  wrote:
> On Thu, May 10, 2018 at 1:34 AM Martin Vaeth  wrote:
>
>> As a simple example, assume that you have read a password file
>> into a string of your language and now access a single password.
>> No matter, how you mark the end of the password (fixed-length, \0, \n,
>> ...) speculative execution might always access the next password(s)
>> unless you prevent it globally. Whether it is exploitable depends
>> of course on other things. There is no difference to C.
>
> [...] I don't see how
> having the next password speculatively read would on its own create a
> vulnerability.

That's what I meant by "whether it is exploitable depends of course
on other things". *Most* speculative executions are probably not
exploitable, whether in C or any other language: you need a
really unfortunate setup.
However, to be on the really safe side you just have to prevent
everything which might potentially exploitable.

> You would also need some kind of indirect memory access
> based on the speculatively-accessed data

For the "classical" spectre (v2?) variant:
In the "speculative" execution you copied more data.
Exploitability depends completely on the subsequent code,
i.e. what will happen with this data (and on whether an attacker
can execute and time the whole function).

However, everybody expected (and perhaps spectre-ng will confirm that)
that there are a lot more of processor bugs involved with speculative
execution: AFAIK, there were already reports that some internal
processor bits were cleared/set depending on some results (i.e.
meltdown type bugs). So maybe just doing the right thing in another
process might reveal some information. Whether it is again possible
to fix this in the kernel is unclear yet.

> Consider:
>
> for x = 1 to 10 : y=5+3 : next x

I don't understand what you want to say here.
Of course, non-sensical code is not exploitable.
The question is whether the compiler can recognize it.
I haven't tried, but I am rather sure that the above loop disappears
in C w/ gcc -O2 due to flow analysis (the constant assertion is
pulled out and then the loop recognized as empty).

> I still tend to think that the additional context around these memory
> accesses that is available in a high-level language could be used by a
> compiler

The compiler needs to detect whether a speculative execution
might be dangerous. This is similarly hard for every Turing-complete
language; I do not see any language having a considerable advantage
for this.




Re: [gentoo-user] Re: Spectre-NG

2018-05-10 Thread Rich Freeman
On Thu, May 10, 2018 at 1:34 AM Martin Vaeth  wrote:

> As a simple example, assume that you have read a password file
> into a string of your language and now access a single password.
> No matter, how you mark the end of the password (fixed-length, \0, \n,
> ...) speculative execution might always access the next password(s)
> unless you prevent it globally. Whether it is exploitable depends
> of course on other things. There is no difference to C.


I'll just reply to this because the rest of the email is just a natural
consequence of it.

I will confess up-front I'm not an expert in Spectre, but I don't see how
having the next password speculatively read would on its own create a
vulnerability.  You would also need some kind of indirect memory access
based on the speculatively-accessed data to create a timing channel.

And of course it is entirely possible that the loop wouldn't be
sequentially reading in data in a way that could cause a bound to be
exceeded, and in this situation I don't see why protection would be
required.  Consider:

for x = 1 to 10 : y=5+3 : next x

This is obviously trivial, but I don't see how executing that loop a few
too many times would cause problems, so blocking speculation is just going
to hurt performance for no benefit.

I still tend to think that the additional context around these memory
accesses that is available in a high-level language could be used by a
compiler to determine when protection is required.

Certainly a skilled programmer might be able to do an even better job if
they were vigilant, but not all programmers are equally skilled...

-- 
Rich



Re: [gentoo-user] Re: Spectre-NG

2018-05-10 Thread Wol's lists

On 09/05/18 23:50, Ian Zimmerman wrote:

Code may be "security-sensitive" but buggy.  Is the compiler writer
really responsible for guessing what the programmer meant to accomplish
with buggy code?


What do you mean by "buggy"?


  It would of course be preferable if the compiler could
just abort with an error when it detects UB, but that turns out to be
very hard to impossible in the case of C.  That's just a built in
problem with the language.


So if the compiler can't detect undefined behaviour, how the hell do you 
expect the programmer to?


Oh - and please explain - what is buggy about wanting the following 
program to compile and actually *do* what the code is asking, rather 
than compiling to a no-op ...


int main () {
  int a, b, c;
  a = 2;
  b = 4;
  c = 6;
}

Note I did say the problem is almost invariably when hardware gets 
involved - what happens if it's


int main () {
  void *a;
  a = 0x00ff;
  *a = 6;
}

and 0x00ff is the address of your network adaptor? Do you want THAT to 
be optimised away "because it doesn't do anything"?


That's why I expect LVM/Clang is much better - because I believe Intel 
is heavily involved they provide guarantees about how the compiler will 
interact with hardware, when the C standard explicitly avoids specifying 
it (imho, the standard should require a compiler to document how it 
handles things like that ...). (Yes I believe there is some compiler 
option to make that work, but I'm pretty certain that either is or was 
undefined behaviour to start with? And if it is now standard, it's 
probably because some clever idiot optimised the "code which doesn't do 
anything" away and they had to define a way of stopping it?)


Cheers,
Wol



[gentoo-user] Re: Spectre-NG

2018-05-09 Thread Martin Vaeth
Rich Freeman  wrote:
> On Wed, May 9, 2018 at 2:18 PM Martin Vaeth  wrote:
>
>> Which would be the horribly slow case I mentioned above.
>
> I'm saying that high-level languages can be made safe.
>
> You're saying that making high-level languages safe comes at a performance
> cost.

A performance cost which is as high as in C, because you simply
have to protect *every* access.
And no, for the same reason as in C, it is not sufficient to do
this only for the array access case; you need to avoid speculative
execution for every conditional, every loop etc.
As a simple example, assume that you have read a password file
into a string of your language and now access a single password.
No matter, how you mark the end of the password (fixed-length, \0, \n,
...) speculative execution might always access the next password(s)
unless you prevent it globally. Whether it is exploitable depends
of course on other things. There is no difference to C.

> lot of C programmers do the same with manual bounds
> checks or equivalent functions like strncpy.

As mentioned above: It plays absolutely no role whether you
know the length a-priori, are looking for a symbol etc.
If you are copying, and the necessary conditional for the end
of the loop is not protected against speculative exection, your
code might be vulnerable to some spectre-type attack.
Actually, in case of short constant length, C is safer here than
most other languages, because it might unroll the loop and thus
avoid the conditional.

>> If slowness is not the issue, one could fix the C compiler in the same way
>> by avoiding speculative exection for every conditional jump.
>
> Sure, but that is way more overhead than necessary.

Also for languages with bound-checks an memory management you need
exactly the same overhead as well if you want to be safe:
Avoiding speculative execution in everything which is compiled into
a conditional.
Of course, in both cases a very careful flow analysis (or instead
requiring hints from the coder in some way) might prevent "safe"
cases. Like in C. There is simply no difference.

> We only need to sterilize these for data passed from an untrusted source

No, unless you know that after the end there cannot be stored
data you need to protect. If a language has means to mark these
data, a compiler might take care of this. But I would count these
cases to "very careful flow analysis or requiring hints from the coder":
One would need language features which are particularly designed
for spectre and which are not useful for much else.
I do not claim that one could not develop such a language.
Maybe there are some languages for which this is not too hard.
However, I think you were speaking about currently existing/used
langauges.

> A high-level language has access to more context and can probably
> more reliably determine which ones need protection.

If you mean by "high-level" a language which is so restrictive
for every conditional that a complete flow-analysis of the
code is trivial, you are right. I do not know such a language,
and I doubt that it could be a Turing-complete one.

> I think that in general language features that more clearly
> separate trusted vs untrusted data would probably help here.

For spectre, the necessary difference is not trusted vs. untrusted,
but worth-to-protect vs. irrelevant-for-every-attacker.
And even then it depends on details of the processor how
far after the end of the string accessed by an unprotected loop
data still is "protected" against spectre.




[gentoo-user] Re: Spectre-NG

2018-05-09 Thread Ian Zimmerman
On 2018-05-09 20:04, Wols Lists wrote:

> > As mentioned, I wonder why gcc/clang do not yet support this
> > horribly slow but spectre-safe option. It can't be that hard to
> > implement in the actual code-producing back-end.
> 
> Given the response by the gcc team to security people complaining that
> gcc was optimising out security-sensitive code (namely, a two-fingered
> salute near enough), I doubt the gcc team would have any interest in
> optimisations that SLOWED DOWN the resultant code.
> 
> I suspect that might be one of the forces driving the kernel towards
> CLANG - a development team that is not obsessed with performance at
> the expense of breaking any code that uses undefined features.

I'm afraid I side with the gcc people in this interminable flamewar.

Code may be "security-sensitive" but buggy.  Is the compiler writer
really responsible for guessing what the programmer meant to accomplish
with buggy code?  It would of course be preferable if the compiler could
just abort with an error when it detects UB, but that turns out to be
very hard to impossible in the case of C.  That's just a built in
problem with the language.

Further, I don't think the llvm/clang position on these cases is all
that different, although there may be a difference in emotional
attitude.

> Unfortunately, when dealing with hardware, one is forced to rely on
> undefined features. A strong point of C, until the compiler decides to
> go "rogue" on you ...

I don't understand what you mean here.  In the disputed cases there was
always a well-defined way (slightly more verbose but not prohibitively
so) to code the desired behavior.

-- 
Please don't Cc: me privately on mailing lists and Usenet,
if you also post the followup to the list or newsgroup.
To reply privately _only_ on Usenet and on broken lists
which rewrite From, fetch the TXT record for no-use.mooo.com.



Re: [gentoo-user] Re: Spectre-NG

2018-05-09 Thread Rich Freeman
On Wed, May 9, 2018 at 2:18 PM Martin Vaeth  wrote:

> Rich Freeman  wrote:
> > On Tue, May 8, 2018 at 4:19 AM Martin Vaeth  wrote:
> >
> >> Rich Freeman  wrote:
> >> >
> >> > Higher-level languages will probably become nearly immune to Spectre
> > just
> >> > as most are nearly immune to buffer overflows.
> >
> >> Quite the opposite: Higher-level languages *always* do some checks
> >> for array-length etc, and it is the _checks_ which are vulnerable.
> >> You can only make them non-vulnerable by making them horribly slow
> >> (by omitting speculative execution completely for the corresponding
> >> conditionals).
> >
> > Sure, but my point is that you CAN make them non-vulnerable by changing
the
> > compiler.

> Which would be the horribly slow case I mentioned above.

I'm saying that high-level languages can be made safe.

You're saying that making high-level languages safe comes at a performance
cost.

These are not in contradiction.  In fact the whole reason low-level
languages still exist to this day (besides legacy code) is that most of the
benefits of high-level languages come at a performance cost. Safety is just
one of them.

This is just as true for buffer overflows and memory management.  If you
take a lot of care, you can avoid the need for bounds checks on every array
access. If you get it wrong, it can go horribly wrong.  High-level
languages tend to compensate by doing bounds checks even when they might
not be needed.  A lot of C programmers do the same with manual bounds
checks or equivalent functions like strncpy.  Again, I'm using buffer
overflows as a more familiar analogy for others - I fully understand that
bounds checks actually make Spectre worse.

> If slowness is not the issue, one could fix the C compiler in the same way
> by avoiding speculative exection for every conditional jump.

Sure, but that is way more overhead than necessary.  We only need to
sterilize these for data passed from an untrusted source (I think).  If a
function declares an internal variable as a loop counter you don't need to
disable speculative execution every time you increment and check the
counter, and a loop is obviously exactly where you want to make this
distinction.

A low level language needs to use heuristics to try to figure out if a
conditional jump is safe to speculatively execute (probably at compile
time).  A high-level language has access to more context and can probably
more reliably determine which ones need protection.  On the other hand it
will probably do a lot more bounds-checking in general.  I'm not sure which
would end up costing more to make reliably safe.

I think that in general language features that more clearly separate
trusted vs untrusted data would probably help here.

-- 
Rich



Re: [gentoo-user] Re: Spectre-NG

2018-05-09 Thread Wols Lists
On 09/05/18 19:18, Martin Vaeth wrote:
> As mentioned, I wonder why gcc/clang do not yet support this
> horribly slow but spectre-safe option. It can't be that hard to
> implement in the actual code-producing back-end. 

Given the response by the gcc team to security people complaining that
gcc was optimising out security-sensitive code (namely, a two-fingered
salute near enough), I doubt the gcc team would have any interest in
optimisations that SLOWED DOWN the resultant code.

I suspect that might be one of the forces driving the kernel towards
CLANG - a development team that is not obsessed with performance at the
expense of breaking any code that uses undefined features.
Unfortunately, when dealing with hardware, one is forced to rely on
undefined features. A strong point of C, until the compiler decides to
go "rogue" on you ...

Cheers,
Wol



[gentoo-user] Re: Spectre-NG

2018-05-09 Thread Martin Vaeth
Rich Freeman  wrote:
> On Tue, May 8, 2018 at 4:19 AM Martin Vaeth  wrote:
>
>> Rich Freeman  wrote:
>> >
>> > Higher-level languages will probably become nearly immune to Spectre
> just
>> > as most are nearly immune to buffer overflows.
>
>> Quite the opposite: Higher-level languages *always* do some checks
>> for array-length etc, and it is the _checks_ which are vulnerable.
>> You can only make them non-vulnerable by making them horribly slow
>> (by omitting speculative execution completely for the corresponding
>> conditionals).
>
> Sure, but my point is that you CAN make them non-vulnerable by changing the
> compiler.

Which would be the horribly slow case I mentioned above.

> On the other hand, if somebody manually does a range check in C the only
> way to fix it is to either fix the source code

If slowness is not the issue, one could fix the C compiler in the same way
by avoiding speculative exection for every conditional jump.

As mentioned, I wonder why gcc/clang do not yet support this
horribly slow but spectre-safe option. It can't be that hard to
implement in the actual code-producing back-end. Only possible
optimization of that code (catching unnecessary cases or
preferring alternative code-paths if there are two many bad
cases) might be tricky, but perhaps this could be postponed
in a first implementation: safety first.




Re: [gentoo-user] Re: Spectre-NG

2018-05-08 Thread Rich Freeman
On Tue, May 8, 2018 at 4:19 AM Martin Vaeth  wrote:

> Rich Freeman  wrote:
> >
> > Higher-level languages will probably become nearly immune to Spectre
just
> > as most are nearly immune to buffer overflows.

> Quite the opposite: Higher-level languages *always* do some checks
> for array-length etc, and it is the _checks_ which are vulnerable.
> You can only make them non-vulnerable by making them horribly slow
> (by omitting speculative execution completely for the corresponding
> conditionals).

Sure, but my point is that you CAN make them non-vulnerable by changing the
compiler.

On the other hand, if somebody manually does a range check in C the only
way to fix it is to either fix the source code (which is about as likely to
work as trying to prevent programmers from create buffer overflows), or use
heuristics to figure out what is going on and apply the fixes
automatically.  That is going to be just as slow, and the compiler might
not be able to catch every situation where it applies.

The compiler doesn't have to guess where the range checks are in a
high-level language because it is the compiler that is doing the range
checks in the first place.

-- 
Rich



[gentoo-user] Re: Spectre-NG

2018-05-08 Thread Martin Vaeth
Rich Freeman  wrote:
>
> Higher-level languages will probably become nearly immune to Spectre just
> as most are nearly immune to buffer overflows.

Quite the opposite: Higher-level languages *always* do some checks
for array-length etc, and it is the _checks_ which are vulnerable.
You can only make them non-vulnerable by making them horribly slow
(by omitting speculative execution completely for the corresponding
conditionals).

The same omission could also be arranged automatically for _every_
C-code (security at the price of a hugh speed cost). I still do
not understand why such an option is not yet implemented in gcc:
AFAIK, none of the current options -mindirect-branch*
-mfunction-return* -fcf-protection=full (though I am not
completely sure about the latter) would protect you automatically
against speculative exection for bound-checking conditional tests.
I am aware that this would cost a lot of speed,
but for certain systems/applications this might be worth.