[PATCH 05/14 v6] Open-code the memcpy() at static TLS initialization time.
Florian Weimer
fweimer@redhat.com
Fri Jun 24 12:42:00 GMT 2016
On 06/07/2016 01:06 PM, Nix wrote:
> From: Nick Alcock <nick.alcock@oracle.com>
>
> This one is a bit nasty. Now that we are initializing TLS earlier for
> the stack canary's sake, existing memcpy() implementations become
> problematic. We can use the multiarch implementations, but they might
> not always be present, and even if they are present they might not always
> be in assembler, so might be compiled with stack-protection. We cannot
> use posix/memcpy.c without marking both it and */wordcopy.c as non-stack-
> protected, which for memcpy() of all things seems like a seriously bad
> idea: if any function in glibc should be stack-protected, it's memcpy()
> (though stack-protecting the many optimized assembly versions is not done
> in this patch series).
Some of the pathnames in this explanation appear to be incorrect.
I looked at the memcpy.c and wordcopy.c implementations, and I do not
see why these functions would need the stack protector. They should not
have addressable local variables, they should all be in registers. As a
result, the implementation should never derive a pointer from the
current stack frame.
These functions might be passed pointers into the callers stack frame,
but the memory looks like this (addresses increase from bottom to top,
so the stack grows downwards on most architectures (except HPPA)):
: :
+-----------------------------+
| Caller stack frame |
| |
| (end of buf) |
| : |
| : |
| char buf[64]; |
| |
+-----------------------------+
| Return address |
| memcpy stack frame |
| |
+-(current top of stack)------+
: :
+=============================+
| XXX guard page XXXXXXXXXXXX |
: :
As a result, a buffer overflow will run away from the return address
associated with the memcpy activation frame. To avoid that, you'd need
a memcpy call with a destination address which points below the current
top of stack before memcpy is called, that is an invalid, dangling
pointer. A random pointer with an excessive size is unlikely to work
because the copying operation would eventually hit the guard page below
the stack. This is not a straight stack-based overflow anymore, and not
something stack protector can help with.
(Attacks against runaway memcpy calls (with size arguments approaching
SIZE_MAX) work against some memcpy implementations not because these
implementations lack stack protector, but because they load variables
from the stack in the inner loop, which may have been overwritten by
attacker-controlled values.)
Anyway, if the above analysis is right, it should be safe to disable
stack protector for functions such as memcpy (essentially doing manually
what -fstack-protector-strong does automatically). This would be my
preferred approach here.
Thanks,
Florian
More information about the Libc-alpha
mailing list