This is the mail archive of the
mailing list for the glibc project.
[PATCH 05/14 v6] Open-code the memcpy() at static TLS initialization time.
- From: Nix <nix at esperi dot org dot uk>
- To: libc-alpha at sourceware dot org
- Cc: fweimer at redhat dot com, Nick Alcock <nick dot alcock at oracle dot com>
- Date: Tue, 7 Jun 2016 12:06:07 +0100
- Subject: [PATCH 05/14 v6] Open-code the memcpy() at static TLS initialization time.
- Authentication-results: sourceware.org; auth=none
- References: <1465297576-10981-1-git-send-email-nix at esperi dot org dot uk>
From: Nick Alcock <email@example.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).
So we have two real options: hack up the guts of posix/memcpy.c and
*/wordcopy.c so that they can be #included (renamed and declared static)
inside libc-tls.c, or simply open-code the memcpy(). For simplicity's
sake, this patch open-codes it, on the grounds that static binaries are
relatively rare and quasi-deprecated anyway, and static binaries with
large TLS sections are yet rarer, and not worth the complexity of hacking
up all the arch-dependent wordcopy files. If the arch provides an inline
assembler memcpy() implementation, we can use that in preference, for
speed; also, of course, if stack protection is not enabled at all, we
can still use a normal memcpy() as before.
(This was not revealed when testing on x86 because on that platform
GCC was open-coding the memcpy() for us.)
v2: New, lets us remove the memcpy() -fno-stack-protection, which wasn't
enough in any case.
v4: Add an inhibit_loop_to_libcall to prevent GCC from turning the loop
back into a memcpy() again. Wrap long lines.
v6: Only do this if stack-protected. Use the inline assembler
ARCH_memcpy if available.
* csu/libc-tls.c (__libc_setup_tls): Add inhibit_loop_to_libcall
to avoid calls to potentially ifunced or stack-protected memcpy.
Optionally open-code the TLS-initialization memcpy.
csu/libc-tls.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index 3d67a64..4d81113 100644
@@ -102,6 +102,7 @@ init_static_tls (size_t memsz, size_t align)
__libc_setup_tls (size_t tcbsize, size_t tcbalign)
@@ -176,8 +177,23 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
_dl_static_dtv.pointer.is_static = true;
- /* sbrk gives us zero'd memory, so we don't need to clear the remainder. */
+ /* sbrk gives us zero'd memory, so we don't need to clear the remainder.
+ When stack-protecting, use inlined asm implementation if available:
+ otherwise, copy by hand, because memcpy() is stack-protected and is often
+ multiarch too. */
+#if defined _HAVE_STRING_ARCH_memcpy || !defined STACK_PROTECTOR_LEVEL
memcpy (_dl_static_dtv.pointer.val, initimage, filesz);
+ char *dst = (char *) _dl_static_dtv.pointer.val;
+ char *src = (char *) initimage;
+ size_t i;
+ for (i = 0; i < filesz; dst++, src++, i++)
+ *dst = *src;
/* Install the pointer to the dtv. */