libc/libthread_xu - Fix segfault caused by libpthread used before initialised
authorMarkus Pfeiffer <markus.pfeiffer@morphism.de>
Mon, 18 Mar 2013 21:46:24 +0000 (21:46 +0000)
committerMarkus Pfeiffer <markus.pfeiffer@morphism.de>
Fri, 22 Mar 2013 22:37:25 +0000 (22:37 +0000)
If a binary has libpthread as dependency and is linked against libintl,
or any other library that uses pthread locking primitives from libc
without depending on libpthread itself it can happen that functions
from libpthread are called before libpthread's constructor has been
called. This leads to a segfault.

This fix adds a weak symbold to libc, namely _pthread_init_early,
which is called from a libc constructor function and therefore makes
sure that libpthread is initialised early enough.

Thanks to Simon Schubert, Angelos Oikonomopoulos, and Sascha Wildner
for the support in debugging this.

lib/libc/gen/_pthread_stubs.c
lib/libthread_xu/thread/thr_init.c

index 2d81c6b..0e188dd 100644 (file)
@@ -96,6 +96,7 @@ WR(stub_zero, pthread_getconcurrency);
 WR(stub_zero, pthread_getprio);
 WR(stub_zero, pthread_getschedparam);
 WR(stub_null, pthread_getspecific);
+WR(stub_empty, pthread_init_early);
 WR(stub_zero, pthread_join);
 WR(stub_zero, pthread_key_create);
 WR(stub_zero, pthread_key_delete);
@@ -216,7 +217,23 @@ stub_true(void)
 }
 
 static void __used
+stub_empty(void)
+{
+}
+
+static void __used
 stub_exit(void)
 {
        exit(0);
 }
+
+/*
+ * If libpthread is loaded, make sure it is initialised before
+ * other libraries call pthread functions
+ */
+void _pthread_init(void) __constructor(0);
+void
+_pthread_init(void)
+{
+       _pthread_init_early();
+}
index 10feb87..2d184a0 100644 (file)
@@ -87,6 +87,8 @@ STATIC_LIB_REQUIRE(_pthread_getprio);
 STATIC_LIB_REQUIRE(_pthread_getschedparam);
 /* thr_info.c */
 STATIC_LIB_REQUIRE(_pthread_set_name_np);
+/* thr_init.c */
+STATIC_LIB_REQUIRE(_pthread_init_early);
 /* thr_join.c */
 STATIC_LIB_REQUIRE(_pthread_join);
 /* thr_kill.c */
@@ -162,6 +164,17 @@ _thread_init(void)
 }
 
 /*
+ * This function is used by libc to initialise libpthread
+ * early during dynamic linking.
+ */
+void _pthread_init_early(void);
+void
+_pthread_init_early(void)
+{
+       _libpthread_init(NULL);
+}
+
+/*
  * Threaded process initialization.
  *
  * This is only called under two conditions:
@@ -341,3 +354,5 @@ init_private(void)
        }
        init_once = 1;
 }
+
+__strong_reference(_pthread_init_early, pthread_init_early);