impose barrier between thread pointer setup and use for static linking
authorRich Felker <dalias@aerifal.cx>
Thu, 18 Oct 2018 02:20:01 +0000 (22:20 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 18 Oct 2018 02:20:01 +0000 (22:20 -0400)
this is the analog of commit 1c84c99913bf1cd47b866ed31e665848a0da84a2
for static linking. unlike with dynamic linking, we don't have
symbolic lookup to use as a barrier. use a dummy (target-agnostic)
degenerate inline asm fragment instead. this technique has precedent
in commit 05ac345f895098657cf44d419b5d572161ebaf43 where it's used for
explicit_bzero. if it proves problematic in any way, loading the
address of the stage 2 function from a pointer object whose address
leaks to kernelspace during thread pointer init could be used as an
even stronger barrier.

src/env/__libc_start_main.c

index 58da9e8308d9e9faa1de90254d355e96b4f27cd8..ba4d21357f215875822ed857be8b6880f4845cdb 100644 (file)
@@ -63,11 +63,24 @@ static void libc_start_init(void)
 
 weak_alias(libc_start_init, __libc_start_init);
 
+static int libc_start_main_stage2(int (*)(int,char **,char **), int, char **);
+
 int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv)
 {
        char **envp = argv+argc+1;
 
        __init_libc(envp, argv[0]);
+
+       /* Barrier against hoisting application code or anything using ssp
+        * or thread pointer prior to its initialization above. */
+       int (*stage2)();
+       __asm__ ( "" : "=r"(stage2) : "r"(libc_start_main_stage2) : "memory" );
+       return stage2(main, argc, argv);
+}
+
+static int libc_start_main_stage2(int (*main)(int,char **,char **), int argc, char **argv)
+{
+       char **envp = argv+argc+1;
        __libc_start_init();
 
        /* Pass control to the application */