Patchwork [10/18] Link libc.so with libc_nonshared.a to pull in __stack_chk_fail_local.

login
register
mail settings
Submitter Nix
Date March 9, 2016, 4 p.m.
Message ID <87oaanmyka.fsf@esperi.org.uk>
Download mbox | patch
Permalink /patch/11286/
State New
Headers show

Comments

Nix - March 9, 2016, 4 p.m.
On 9 Mar 2016, Andreas Schwab said:

> Nix <nix@esperi.org.uk> writes:
>
>> How does one do that in the glibc makefile scheme of things?
>
> You can create it under a new name and put it in shared-only-routines.

... oh! Of course, just because the filename is different doesn't mean
it can't export the same symbols, and because it's hidden it can never
conflict with anything.

Andreas's infuriating "Socratic review" style wins again, I think.

[pause]

Yes, that seems to work on x86-64 and sparc64, though I still have to
throw it through a full test cycle to be sure this is true with many
configure flag combos and bitnesses. It also means we can drop the
__stack_chk_fail -> __stack_chk_fail_local symbol hack from the static
libcs and only keep it in the shared one, since the only reason it was
there in the static one was because things were being dragged into
libc.so from libc_nonshared.a.

This was an unsatisfactory bit of the patch series, in hindsight: I hope
you like the replacement better.

I chose to augment the value of shared-only-routines for the sake of the
rtld recursion stage: static-only-routines is only assigned with := here
because its previous value, modified during the rtld recursion, is used
to augment $(routines) immediately above.

Provisional patch (real thing will land in the next series I post, v6,
in addition to the limitation of the symbol-hack to SHARED, which is in
a different patch in the series):

From 4360b8f9115f0408ff36ee5779cb0b9daae7264b Mon Sep 17 00:00:00 2001
From: Nick Alcock <nick.alcock@oracle.com>
Date: Fri, 19 Feb 2016 18:49:16 +0000
Subject: [PATCH] Add stack_chk_fail_local to libc.so.

This is required by the next commit, which routes all
__stack_chk_fail() calls in libc.so via this function to avoid
the PLT.  It has be duplicated in libc.so and libc_nonshared.a
because its entire reason for existence is to be hidden and avoid
the PLT, so the copy in libc.so is not visible from elsewhere.

Also stop all the variants of __stack_chk_fail from being stack-
protected: this makes no sense and risks recursion.

v5: Better explanation.  Add no-stack-protection of
    __stack_chk_fail_local etc.
v6: Rework as suggested by Andreas: make a shared-only version of
    stack_chk_fail_local.c rather than linking libc_nonshared into
    libc.

	* debug/libc-stack_chk_fail_local.c: New file.
	* debug/Makefile (routines): Add it.
	(shared-only-routines): Likewise.
	(CFLAGS-stack_chk_fail.c): Use $(no-stack-protector).
	(CFLAGS-stack_chk_fail_local.c): Likewise.
	(CFLAGS-libc-stack_chk_fail_local.c): Likewise.
---
 debug/Makefile                    | 14 +++++++++++++-
 debug/libc-stack_chk_fail_local.c |  3 +++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 debug/libc-stack_chk_fail_local.c

Patch

diff --git a/debug/Makefile b/debug/Makefile
index 6b5f31e..27da081 100644
--- a/debug/Makefile
+++ b/debug/Makefile
@@ -48,9 +48,21 @@  routines  = backtrace backtracesyms backtracesymsfd noophooks \
 	    vdprintf_chk obprintf_chk \
 	    longjmp_chk ____longjmp_chk \
 	    fdelt_chk poll_chk ppoll_chk \
-	    stack_chk_fail fortify_fail \
+	    stack_chk_fail fortify_fail libc-stack_chk_fail_local \
 	    $(static-only-routines)
+
+# stack_chk_fail_local must be non-PIC, thus static-only, but we also
+# want an identical thunk hidden in libc.so to avoid going via the PLT.
+
 static-only-routines := warning-nop stack_chk_fail_local
+shared-only-routines += libc-stack_chk_fail_local
+
+# Building the stack-protector failure routines with stack protection
+# makes no sense.
+
+CFLAGS-stack_chk_fail.c = $(no-stack-protector)
+CFLAGS-stack_chk_fail_local.c = $(no-stack-protector)
+CFLAGS-libc-stack_chk_fail_local.c = $(no-stack-protector)
 
 CFLAGS-backtrace.c = -fno-omit-frame-pointer
 CFLAGS-sprintf_chk.c = $(libio-mtsafe)
diff --git a/debug/libc-stack_chk_fail_local.c b/debug/libc-stack_chk_fail_local.c
new file mode 100644
index 0000000..73da970
--- /dev/null
+++ b/debug/libc-stack_chk_fail_local.c
@@ -0,0 +1,3 @@ 
+/* This goes into the shared libc.  */
+
+#include <stack_chk_fail_local.c>