Module: xenomai-jki
Branch: for-forge
Commit: ce93be10341beb8c1f7a59a462307f3f8a4aec0a
URL:    
http://git.xenomai.org/?p=xenomai-jki.git;a=commit;h=ce93be10341beb8c1f7a59a462307f3f8a4aec0a

Author: Jan Kiszka <jan.kis...@siemens.com>
Date:   Mon Jan  5 15:48:14 2015 +0100

lib/cobalt: Fix ordering of fork handler

Currently, fork handlers run in more or less random order. This could
cause the heap being unmapped after __init_cobalt was executed, leaving
cobalt_current_window in an invalid state. This caused, e.g., crashes of
the sysregd when run as unprivileged user, thus when it forked to run
fusermount with root privileges.

Fix the issue by performing the after-fork work centrally, in a
well-defined order.

Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>

---

 lib/cobalt/current.c  |    8 ++------
 lib/cobalt/current.h  |    2 ++
 lib/cobalt/init.c     |   29 +++++++++++++++++++----------
 lib/cobalt/internal.h |    2 ++
 lib/cobalt/printf.c   |    3 +--
 lib/cobalt/umm.c      |    4 +---
 lib/cobalt/umm.h      |    2 ++
 7 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/lib/cobalt/current.c b/lib/cobalt/current.c
index b7d5b6e..a8bc330 100644
--- a/lib/cobalt/current.c
+++ b/lib/cobalt/current.c
@@ -26,8 +26,6 @@
 
 static DEFINE_PRIVATE_LIST(tsd_hooks);
 
-static void child_fork_handler(void);
-
 #ifdef HAVE_TLS
 
 __thread __attribute__ ((tls_model (CONFIG_XENO_TLS_MODEL)))
@@ -53,7 +51,7 @@ static inline void __cobalt_clear_tsd(void)
 
 static void init_current_keys(void)
 {
-       pthread_atfork(NULL, NULL, &child_fork_handler);
+       cobalt_current = XN_NO_HANDLE;
 }
 
 #else /* !HAVE_TLS */
@@ -85,8 +83,6 @@ static void init_current_keys(void)
        if (err)
                goto error_exit;
 
-       pthread_atfork(NULL, NULL, &child_fork_handler);
-
        err = pthread_key_create(&cobalt_current_window_key, NULL);
        if (err) {
          error_exit:
@@ -97,7 +93,7 @@ static void init_current_keys(void)
 
 #endif /* !HAVE_TLS */
 
-static void child_fork_handler(void)
+void cobalt_clear_tsd(void)
 {
        struct cobalt_tsd_hook *th;
 
diff --git a/lib/cobalt/current.h b/lib/cobalt/current.h
index 3e28b83..069ee1c 100644
--- a/lib/cobalt/current.h
+++ b/lib/cobalt/current.h
@@ -93,4 +93,6 @@ void cobalt_init_current_keys(void);
 
 void cobalt_set_tsd(__u32 u_winoff);
 
+void cobalt_clear_tsd(void);
+
 #endif /* _LIB_COBALT_CURRENT_H */
diff --git a/lib/cobalt/init.c b/lib/cobalt/init.c
index dfe1150..b7c8f76 100644
--- a/lib/cobalt/init.c
+++ b/lib/cobalt/init.c
@@ -107,6 +107,24 @@ static void low_init(void)
 
 static void __init_cobalt(void);
 
+static void cobalt_fork_handler(void)
+{
+       cobalt_unmap_umm();
+       cobalt_clear_tsd();
+       cobalt_print_init_atfork();
+#ifdef HAVE_PTHREAD_ATFORK
+       /*
+        * Upon fork, in case the parent required init deferral, this
+        * is the forkee's responsibility to call __libcobalt_init()
+        * for bootstrapping the services the same way. On systems
+        * with no fork() support, clients are not supposed to, well,
+        * fork in the first place, so we don't take any provision for
+        * this event.
+        */
+       __init_cobalt();
+#endif
+}
+
 void __libcobalt_init(void)
 {
        struct sigaction sa;
@@ -118,21 +136,12 @@ void __libcobalt_init(void)
        sa.sa_flags = SA_SIGINFO;
        sigaction(SIGDEBUG, &sa, &__cobalt_orig_sigdebug);
 
-#ifdef HAVE_PTHREAD_ATFORK
        /*
-        * Upon fork, in case the parent required init deferral, this
-        * is the forkee's responsibility to call __libcobalt_init()
-        * for bootstrapping the services the same way. On systems
-        * with no fork() support, clients are not supposed to, well,
-        * fork in the first place, so we don't take any provision for
-        * this event.
-        *
         * NOTE: a placeholder for pthread_atfork() may return an
         * error status with uClibc, so we don't check the return
         * value on purpose.
         */
-       pthread_atfork(NULL, NULL, __init_cobalt);
-#endif
+       pthread_atfork(NULL, NULL, cobalt_fork_handler);
 
        if (sizeof(struct cobalt_mutex_shadow) > sizeof(pthread_mutex_t)) {
                report_error("sizeof(pthread_mutex_t): %d <"
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index c7350be..e126480 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -45,6 +45,8 @@ void cobalt_thread_init(void);
 
 void cobalt_print_init(void);
 
+void cobalt_print_init_atfork(void);
+
 void cobalt_print_exit(void);
 
 void cobalt_ticks_init(unsigned long long freq);
diff --git a/lib/cobalt/printf.c b/lib/cobalt/printf.c
index e391f96..f19f4ea 100644
--- a/lib/cobalt/printf.c
+++ b/lib/cobalt/printf.c
@@ -670,7 +670,7 @@ static void spawn_printer_thread(void)
        pthread_create(&printer_thread, &thattr, printer_loop, NULL);
 }
 
-static void forked_child_init(void)
+void cobalt_print_init_atfork(void)
 {
        struct print_buffer *my_buffer = pthread_getspecific(buffer_key);
        struct print_buffer **pbuffer = &first_buffer;
@@ -791,7 +791,6 @@ void cobalt_print_init(void)
        pthread_cond_init(&printer_wakeup, NULL);
 
        spawn_printer_thread();
-       pthread_atfork(NULL, NULL, forked_child_init);
 
        rt_print_auto_init(1);
        atexit(rt_print_flush_buffers);
diff --git a/lib/cobalt/umm.c b/lib/cobalt/umm.c
index a09b2d6..4a881a3 100644
--- a/lib/cobalt/umm.c
+++ b/lib/cobalt/umm.c
@@ -75,7 +75,7 @@ static void *__map_umm(const char *name, uint32_t *size_r)
 
 #define map_umm(__name, __size_r)  __map_umm("/dev/rtdm/" __name, __size_r)
 
-static void unmap_on_fork(void)
+void cobalt_unmap_umm(void)
 {
        void *addr;
 
@@ -121,8 +121,6 @@ static void init_loadup(__u32 vdso_offset)
 {
        uint32_t size;
 
-       pthread_atfork(NULL, NULL, unmap_on_fork);
-
        cobalt_umm_shared = map_umm(COBALT_MEMDEV_SHARED, &size);
        if (cobalt_umm_shared == MAP_FAILED) {
                report_error("cannot map shared umm area: %s",
diff --git a/lib/cobalt/umm.h b/lib/cobalt/umm.h
index 5647758..b592968 100644
--- a/lib/cobalt/umm.h
+++ b/lib/cobalt/umm.h
@@ -22,6 +22,8 @@
 
 void cobalt_init_umm(__u32 vdso_offset);
 
+void cobalt_unmap_umm(void);
+
 struct xnvdso;
 
 extern struct xnvdso *cobalt_vdso;


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to