On Thursday, 22 September 2016 at 12:08:19 UTC, Steven
Schveighoffer wrote:
On 9/20/16 12:45 PM, cym13 wrote:
On Tuesday, 20 September 2016 at 14:00:00 UTC, Steven
Schveighoffer wrote:
Dereferencing a null pointer is perfectly safe in user space
(where
you can't map the zero page). Indexing a null pointer is not.
In this
case, we are indexing a null pointer, so there is the
potential for
abuse, but very very small.
Note that not all operating systems disallow mapping the zero
page
(although they admitedly should). And yes the potential for
abuse is
small, I've just getting annoyed at dangerous generalities.
We can simply avoid supporting such OSes, I don't think we lose
much! But thanks for pointing this out, I didn't know that.
We lose at least all linux kernels before 2.6.23... although it
sounds reasonnable it's a choice that's better made knowingly ;)
In that specific case I don't think it should be treated as a
security
issue in the general case although it could become one if used
in an
unfavorable environment.
I had an interesting thought, and this is actually a @safe
issue (I'll file an issue request). If you have a potentially
large enough struct, then accessing items in that struct has
the potential to go beyond the unmapped memory.
However, in MOST cases, the compiler knows the offset being
used (especially if accessing specific members). In some cases
it doesn't. But one thing the compiler can do (at least in
@safe code) is:
1. If the index is known at compile time to go beyond one page
(or beyond the known OS limit for unmapped pages), do a null
pointer check first, and abort with segfault if possible. As
simple as loading the byte/word at the front of the struct. You
also only have to do this once if the struct pointer does not
move.
2. If the index is not known until runtime (for instance,
indexing a static array in a struct), then check for null
pointer before dereferencing conservatively.
This would make code that is very common (i.e. small struct
size, or accessing front members of the struct) just use the
hardware features to prevent access. Code that is rare
(accessing members beyond one page of size) can be instrumented
to ensure no exploits are possible.
-Steve
This is very interesting, I'm sure there are ways to expand on
this idea further (but even just that would be a real
improvement). One thing is that although I don't see people
willingly creating such a big struct not all D code is written by
humans and with some mixin or template help it's a possibility.
I'd love to see some protection where the compiler can work it
out.