From 8870140ff0d730c5c71c2170518c6c7957c4d68c Mon Sep 17 00:00:00 2001 From: rofl0r Date: Thu, 26 May 2016 10:48:32 +0100 Subject: [PATCH] don't call INIT() from close hook it was observed that it is a bad idea to initialize the entire infrastructure used by proxychains from the close hook, because the following scenario will lead to a deadlock: - it is possible that the dynlinker executes the initializer code of other shared libs first - if that code directly or indirectly calls malloc() - which calls close() if it decided to use an mmap based allocation - will now call our close(), which does - call pthread_once which requires a lock - creates a thread which calls malloc() - which in turn calls our close() another time - and our close is still in locked state. so it seems the only save thing to do is to just get the address of the original close function, and call that when we're in a pre-init state. this may hold for other functions that do lazy initialization as well, however for those just calling the original function is probably undesired since that could result in unproxified connections. it will be needed to analyze on a per-function basis what the best thing to do is, and finally rely only on the execution of the init function from the gcc initializer. should fix #119 --- src/libproxychains.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libproxychains.c b/src/libproxychains.c index ec18496..d8fab4c 100644 --- a/src/libproxychains.c +++ b/src/libproxychains.c @@ -93,7 +93,7 @@ static void* load_sym(char* symname, void* proxyfunc) { #define INIT() init_lib_wrapper(__FUNCTION__) -#define SETUP_SYM(X) do { true_ ## X = load_sym( # X, X ); } while(0) +#define SETUP_SYM(X) do { if (! true_ ## X ) true_ ## X = load_sym( # X, X ); } while(0) #include "allocator_thread.h" @@ -304,7 +304,10 @@ static void get_chain_data(proxy_data * pd, unsigned int *proxy_count, chain_typ /******* HOOK FUNCTIONS *******/ int close(int fd) { - INIT(); + if(!init_l) { + SETUP_SYM(close); + return true_close(fd); + } /* prevent rude programs (like ssh) from closing our pipes */ if(fd != req_pipefd[0] && fd != req_pipefd[1] && fd != resp_pipefd[0] && fd != resp_pipefd[1]) {