swrap: Avoid symbol binding deadlocks during fork
authorAndreas Schneider <asn@samba.org>
Mon, 27 Nov 2017 10:00:54 +0000 (11:00 +0100)
committerAndreas Schneider <asn@samba.org>
Mon, 4 Dec 2017 11:23:47 +0000 (12:23 +0100)
If there is a signal handler defined, e.g. for SIGCHILD and this signal
handler is called during pthread_atfork() has just locked all mutexes
and we want to check if a symbol is bound, we end up in a deadlock.

(gdb) bt
 0  __lll_lock_wait () at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:135
 1  0x00007fe48837aef5 in __GI___pthread_mutex_lock (mutex=0x7fe4889a71c0 <libc_symbol_binding_mutex>) at ../nptl/pthread_mutex_lock.c:80
 2  0x00007fe48879b2f1 in libc_write (fd=14, buf=0x7ffdad6436e8, count=8) at /home/asn/workspace/projects/socket_wrapper/src/socket_wrapper.c:1070
 3  0x00007fe4887a21cb in swrap_write (s=14, buf=0x7ffdad6436e8, len=8) at /home/asn/workspace/projects/socket_wrapper/src/socket_wrapper.c:5137
 4  0x00007fe4887a2359 in write (s=14, buf=0x7ffdad6436e8, len=8) at /home/asn/workspace/projects/socket_wrapper/src/socket_wrapper.c:5171
 5  0x00007fe48713e5f2 in tevent_common_wakeup_fd (fd=14) at ../lib/tevent/tevent.c:959
 6  0x00007fe48713e61f in tevent_common_wakeup (ev=ev@entry=0x55d04922e280) at ../lib/tevent/tevent.c:975
 7  0x00007fe487141d38 in tevent_common_signal_handler (signum=<optimized out>) at ../lib/tevent/tevent_signal.c:109
 8  <signal handler called>
 9  0x00007fe4844de081 in __libc_fork () at ../sysdeps/nptl/fork.c:135
 10 0x000055d047e8ddb3 in smbd_accept_connection (ev=0x55d04922e280, fde=<optimized out>, flags=<optimized out>, private_data=<optimized out>)
    at ../source3/smbd/server.c:992

Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
src/socket_wrapper.c

index f6d7e244e60441adaa0fe2b2dcb7de891b76e9db..539d27dbc9ddfeec7a63b740ebbb577ea48a49ca 100644 (file)
@@ -671,28 +671,34 @@ static void *_swrap_bind_symbol(enum swrap_lib lib, const char *fn_name)
 }
 
 #define swrap_bind_symbol_libc(sym_name) \
-       SWRAP_LOCK(libc_symbol_binding); \
        if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
-               swrap.libc.symbols._libc_##sym_name.obj = \
-                       _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
-       } \
-       SWRAP_UNLOCK(libc_symbol_binding)
+               SWRAP_LOCK(libc_symbol_binding); \
+               if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
+                       swrap.libc.symbols._libc_##sym_name.obj = \
+                               _swrap_bind_symbol(SWRAP_LIBC, #sym_name); \
+               } \
+               SWRAP_UNLOCK(libc_symbol_binding); \
+       }
 
 #define swrap_bind_symbol_libsocket(sym_name) \
-       SWRAP_LOCK(libc_symbol_binding); \
        if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
-               swrap.libc.symbols._libc_##sym_name.obj = \
-                       _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
-       } \
-       SWRAP_UNLOCK(libc_symbol_binding)
+               SWRAP_LOCK(libc_symbol_binding); \
+               if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
+                       swrap.libc.symbols._libc_##sym_name.obj = \
+                               _swrap_bind_symbol(SWRAP_LIBSOCKET, #sym_name); \
+               } \
+               SWRAP_UNLOCK(libc_symbol_binding); \
+       }
 
 #define swrap_bind_symbol_libnsl(sym_name) \
-       SWRAP_LOCK(libc_symbol_binding); \
        if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
-               swrap.libc.symbols._libc_##sym_name.obj = \
-                       _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
-       } \
-       SWRAP_UNLOCK(libc_symbol_binding)
+               SWRAP_LOCK(libc_symbol_binding); \
+               if (swrap.libc.symbols._libc_##sym_name.obj == NULL) { \
+                       swrap.libc.symbols._libc_##sym_name.obj = \
+                               _swrap_bind_symbol(SWRAP_LIBNSL, #sym_name); \
+               } \
+               SWRAP_UNLOCK(libc_symbol_binding); \
+       }
 
 /****************************************************************************
  *                               IMPORTANT