[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [torsocks/master] Ensure that torsocks initializes itself in the presence of C++.
commit d45e4f2329e2630a9471ea72a48e9c77556100f1
Author: Yawning Angel <yawning@xxxxxxxxxxxxxxx>
Date: Sun Apr 5 06:55:11 2015 +0000
Ensure that torsocks initializes itself in the presence of C++.
Fun fact, `__attribute__(constructor)` functions aren't guaranteed to be
called before C++ static object constructors. This change ensures that
initialization will always be called once (and only once), as needed
even if C++ codebases chose to use hijacked symbols in ctors for static
objects.
Things that got changed:
* Added `tsocks_once()` that is a functional replica of pthread_once,
but doesn't require linking in a real pthread library if the
application does not.
* Changed the initialization/cleanup to use tsocks_once.
* Call the initialization from within all of the hijacked libc calls.
Fixes bug #15584.
Signed-off-by: Yawning Angel <yawning@xxxxxxxxxxxxxxx>
Signed-off-by: David Goulet <dgoulet@xxxxxxxxx>
---
src/common/compat.c | 25 +++++++++++++++++++++++++
src/common/compat.h | 14 +++++++++++++-
src/common/connection.c | 11 +----------
src/common/connection.h | 1 -
src/lib/accept.c | 2 ++
src/lib/close.c | 3 +++
src/lib/connect.c | 2 ++
src/lib/fclose.c | 5 ++++-
src/lib/getaddrinfo.c | 1 +
src/lib/gethostbyname.c | 6 ++++++
src/lib/getpeername.c | 1 +
src/lib/listen.c | 1 +
src/lib/recv.c | 2 +-
src/lib/sendto.c | 1 +
src/lib/socket.c | 2 ++
src/lib/socketpair.c | 2 +-
src/lib/syscall.c | 1 +
src/lib/torsocks.c | 42 ++++++++++++++++++++++--------------------
src/lib/torsocks.h | 1 +
19 files changed, 88 insertions(+), 35 deletions(-)
diff --git a/src/common/compat.c b/src/common/compat.c
index 7d8431d..a861b3d 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -71,4 +71,29 @@ void tsocks_mutex_unlock(tsocks_mutex_t *m)
assert(!ret);
}
+/*
+ * Call the given routine once, and only once. tsocks_once returning
+ * guarantees that the routine has succeded.
+ */
+void tsocks_once(tsocks_once_t *o, void (*init_routine)(void))
+{
+
+ /* Why, yes, pthread_once(3P) exists. Said routine requires linking in a
+ * real pthread library on Linux, while this does not and will do the right
+ * thing even with the stub implementation. */
+ assert(o);
+
+ /* This looks scary and incorrect, till you realize that the
+ * pthread_mutex routines include memory barriers. */
+ if (!o->once) {
+ return;
+ }
+ tsocks_mutex_lock(&o->mutex);
+ if (o->once) {
+ init_routine();
+ o->once = 0;
+ }
+ tsocks_mutex_unlock(&o->mutex);
+}
+
#endif /* __GLIBC__, __darwin__, __FreeBSD__, __NetBSD__ */
diff --git a/src/common/compat.h b/src/common/compat.h
index e7e5812..ce47129 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -33,14 +33,26 @@ typedef struct tsocks_mutex_t {
} tsocks_mutex_t;
/* Define a tsock mutex variable with the mutex statically initialized. */
+#define TSOCKS_MUTEX_INIT { .mutex = PTHREAD_MUTEX_INITIALIZER }
#define TSOCKS_INIT_MUTEX(name) \
- tsocks_mutex_t name = { .mutex = PTHREAD_MUTEX_INITIALIZER }
+ tsocks_mutex_t name = TSOCKS_MUTEX_INIT
void tsocks_mutex_init(tsocks_mutex_t *m);
void tsocks_mutex_destroy(tsocks_mutex_t *m);
void tsocks_mutex_lock(tsocks_mutex_t *m);
void tsocks_mutex_unlock(tsocks_mutex_t *m);
+typedef struct tsocks_once_t {
+ int once:1;
+ tsocks_mutex_t mutex;
+} tsocks_once_t;
+
+/* Define a tsock once variable, statically initialized. */
+#define TSOCKS_INIT_ONCE(name) \
+ tsocks_once_t name = { .once = 1, .mutex = TSOCKS_MUTEX_INIT }
+
+void tsocks_once(tsocks_once_t *o, void (*init_routine)(void));
+
#else
#error "OS not supported."
#endif /* __GLIBC__, __darwin__, __FreeBSD__, __NetBSD__ */
diff --git a/src/common/connection.c b/src/common/connection.c
index 4c75579..d4ae722 100644
--- a/src/common/connection.c
+++ b/src/common/connection.c
@@ -82,7 +82,7 @@ static inline unsigned int conn_hash_fct(struct connection *c)
/*
* Declare the connection registry.
*/
-static HT_HEAD(connection_registry, connection) connection_registry_root;
+static HT_HEAD(connection_registry, connection) connection_registry_root = HT_INITIALIZER();
HT_PROTOTYPE(connection_registry, connection, node, conn_hash_fct,
conn_equal_fct);
HT_GENERATE(connection_registry, connection, node, conn_hash_fct,
@@ -107,15 +107,6 @@ void connection_registry_unlock(void)
}
/*
- * Initialize connection registry.
- */
-ATTR_HIDDEN
-void connection_registry_init(void)
-{
- HT_INIT(connection_registry, &connection_registry_root);
-}
-
-/*
* Set an already allocated connection address using the given IPv4/6 address,
* domain and port.
*
diff --git a/src/common/connection.h b/src/common/connection.h
index 379f158..3c958b7 100644
--- a/src/common/connection.h
+++ b/src/common/connection.h
@@ -81,7 +81,6 @@ void connection_destroy(struct connection *conn);
void connection_remove(struct connection *conn);
void connection_insert(struct connection *conn);
-void connection_registry_init(void);
void connection_registry_lock(void);
void connection_registry_unlock(void);
diff --git a/src/lib/accept.c b/src/lib/accept.c
index e9bc36c..21714cb 100644
--- a/src/lib/accept.c
+++ b/src/lib/accept.c
@@ -85,6 +85,7 @@ error:
LIBC_ACCEPT_DECL
{
if (!tsocks_libc_accept) {
+ tsocks_initialize();
tsocks_libc_accept = tsocks_find_libc_symbol(
LIBC_ACCEPT_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
@@ -158,6 +159,7 @@ error:
LIBC_ACCEPT4_DECL
{
if (!tsocks_libc_accept4) {
+ tsocks_initialize();
tsocks_libc_accept4 = tsocks_find_libc_symbol(
LIBC_ACCEPT4_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/close.c b/src/lib/close.c
index d774c85..7fb9e53 100644
--- a/src/lib/close.c
+++ b/src/lib/close.c
@@ -61,5 +61,8 @@ LIBC_CLOSE_RET_TYPE tsocks_close(LIBC_CLOSE_SIG)
*/
LIBC_CLOSE_DECL
{
+ if (!tsocks_libc_close) {
+ tsocks_initialize();
+ }
return tsocks_close(LIBC_CLOSE_ARGS);
}
diff --git a/src/lib/connect.c b/src/lib/connect.c
index 1bf81ac..2480643 100644
--- a/src/lib/connect.c
+++ b/src/lib/connect.c
@@ -231,5 +231,7 @@ error:
*/
LIBC_CONNECT_DECL
{
+ if (!tsocks_libc_connect)
+ tsocks_initialize();
return tsocks_connect(LIBC_CONNECT_ARGS);
}
diff --git a/src/lib/fclose.c b/src/lib/fclose.c
index 8d371cd..b6f3251 100644
--- a/src/lib/fclose.c
+++ b/src/lib/fclose.c
@@ -76,10 +76,13 @@ error:
*/
LIBC_FCLOSE_DECL
{
+ /* fclose(3) is unique in that it does not call torsocks_initialize(), as
+ * it is used from within the initialization routine to close the config
+ * file/log file. This would be a problem, except that all of the global
+ * state it depends on is statically initialized. */
if (!tsocks_libc_fclose) {
tsocks_libc_fclose = tsocks_find_libc_symbol(
LIBC_FCLOSE_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
-
return tsocks_fclose(LIBC_FCLOSE_ARGS);
}
diff --git a/src/lib/getaddrinfo.c b/src/lib/getaddrinfo.c
index 0f7fd4f..846eddb 100644
--- a/src/lib/getaddrinfo.c
+++ b/src/lib/getaddrinfo.c
@@ -128,6 +128,7 @@ error:
LIBC_GETADDRINFO_DECL
{
if (!tsocks_libc_getaddrinfo) {
+ tsocks_initialize();
tsocks_libc_getaddrinfo = tsocks_find_libc_symbol(
LIBC_GETADDRINFO_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/gethostbyname.c b/src/lib/gethostbyname.c
index 322f398..93a3483 100644
--- a/src/lib/gethostbyname.c
+++ b/src/lib/gethostbyname.c
@@ -109,6 +109,7 @@ error:
*/
LIBC_GETHOSTBYNAME_DECL
{
+ tsocks_initialize();
return tsocks_gethostbyname(LIBC_GETHOSTBYNAME_ARGS);
}
@@ -137,6 +138,7 @@ LIBC_GETHOSTBYNAME2_RET_TYPE tsocks_gethostbyname2(LIBC_GETHOSTBYNAME2_SIG)
*/
LIBC_GETHOSTBYNAME2_DECL
{
+ tsocks_initialize();
return tsocks_gethostbyname2(LIBC_GETHOSTBYNAME2_ARGS);
}
@@ -202,6 +204,7 @@ error:
*/
LIBC_GETHOSTBYADDR_DECL
{
+ tsocks_initialize();
return tsocks_gethostbyaddr(LIBC_GETHOSTBYADDR_ARGS);
}
@@ -305,6 +308,7 @@ error:
*/
LIBC_GETHOSTBYADDR_R_DECL
{
+ tsocks_initialize();
return tsocks_gethostbyaddr_r(LIBC_GETHOSTBYADDR_R_ARGS);
}
@@ -380,6 +384,7 @@ error:
*/
LIBC_GETHOSTBYNAME_R_DECL
{
+ tsocks_initialize();
return tsocks_gethostbyname_r(LIBC_GETHOSTBYNAME_R_ARGS);
}
@@ -410,5 +415,6 @@ LIBC_GETHOSTBYNAME2_R_RET_TYPE tsocks_gethostbyname2_r(LIBC_GETHOSTBYNAME2_R_SIG
*/
LIBC_GETHOSTBYNAME2_R_DECL
{
+ tsocks_initialize();
return tsocks_gethostbyname2_r(LIBC_GETHOSTBYNAME2_R_ARGS);
}
diff --git a/src/lib/getpeername.c b/src/lib/getpeername.c
index d8bf701..2f976a4 100644
--- a/src/lib/getpeername.c
+++ b/src/lib/getpeername.c
@@ -98,6 +98,7 @@ libc:
LIBC_GETPEERNAME_DECL
{
if (!tsocks_libc_getpeername) {
+ tsocks_initialize();
tsocks_libc_getpeername = tsocks_find_libc_symbol(
LIBC_GETPEERNAME_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/listen.c b/src/lib/listen.c
index 38c37d8..5f675c4 100644
--- a/src/lib/listen.c
+++ b/src/lib/listen.c
@@ -80,6 +80,7 @@ error:
LIBC_LISTEN_DECL
{
if (!tsocks_libc_listen) {
+ tsocks_initialize();
tsocks_libc_listen = tsocks_find_libc_symbol(
LIBC_LISTEN_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/recv.c b/src/lib/recv.c
index 6e8a20a..1ff1446 100644
--- a/src/lib/recv.c
+++ b/src/lib/recv.c
@@ -179,7 +179,7 @@ error:
LIBC_RECVMSG_DECL
{
if (!tsocks_libc_recvmsg) {
- /* Find symbol if not already set. Exit if not found. */
+ tsocks_initialize();
tsocks_libc_recvmsg = tsocks_find_libc_symbol(LIBC_RECVMSG_NAME_STR,
TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/sendto.c b/src/lib/sendto.c
index 3362026..6b1d3ff 100644
--- a/src/lib/sendto.c
+++ b/src/lib/sendto.c
@@ -73,6 +73,7 @@ libc_sendto:
LIBC_SENDTO_DECL
{
if (!tsocks_libc_sendto) {
+ tsocks_initialize();
tsocks_libc_sendto = tsocks_find_libc_symbol(
LIBC_SENDTO_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/socket.c b/src/lib/socket.c
index bdac610..edc24ab 100644
--- a/src/lib/socket.c
+++ b/src/lib/socket.c
@@ -72,5 +72,7 @@ end:
*/
LIBC_SOCKET_DECL
{
+ if (!tsocks_libc_socket)
+ tsocks_initialize();
return tsocks_socket(LIBC_SOCKET_ARGS);
}
diff --git a/src/lib/socketpair.c b/src/lib/socketpair.c
index c1c70f7..263e4d8 100644
--- a/src/lib/socketpair.c
+++ b/src/lib/socketpair.c
@@ -48,7 +48,7 @@ LIBC_SOCKETPAIR_RET_TYPE tsocks_socketpair(LIBC_SOCKETPAIR_SIG)
LIBC_SOCKETPAIR_DECL
{
if (!tsocks_libc_socketpair) {
- /* Find symbol if not already set. Exit if not found. */
+ tsocks_initialize();
tsocks_libc_socketpair = tsocks_find_libc_symbol(
LIBC_SOCKETPAIR_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/syscall.c b/src/lib/syscall.c
index c3bbd56..8b24f4c 100644
--- a/src/lib/syscall.c
+++ b/src/lib/syscall.c
@@ -480,6 +480,7 @@ LIBC_SYSCALL_DECL
va_list args;
if (!tsocks_libc_syscall) {
+ tsocks_initialize();
tsocks_libc_syscall= tsocks_find_libc_symbol(
LIBC_SYSCALL_NAME_STR, TSOCKS_SYM_EXIT_NOT_FOUND);
}
diff --git a/src/lib/torsocks.c b/src/lib/torsocks.c
index 5734af1..8f079fe 100644
--- a/src/lib/torsocks.c
+++ b/src/lib/torsocks.c
@@ -47,8 +47,11 @@ struct configuration tsocks_config;
*/
struct onion_pool tsocks_onion_pool;
+/* Indicate if the library was initialized previously. */
+static TSOCKS_INIT_ONCE(init_once);
+
/* Indicate if the library was cleaned up previously. */
-unsigned int tsocks_cleaned_up = 0;
+static TSOCKS_INIT_ONCE(term_once);
/*
* Set to 1 if the binary is set with suid or 0 if not. This is set once during
@@ -273,7 +276,7 @@ static void init_logging(void)
* Lib constructor. Initialize torsocks here before the main execution of the
* binary we are preloading.
*/
-static void __attribute__((constructor)) tsocks_init(void)
+static void tsocks_init(void)
{
int ret;
@@ -293,9 +296,6 @@ static void __attribute__((constructor)) tsocks_init(void)
*/
init_config();
- /* Initialize connection reigstry. */
- connection_registry_init();
-
/*
* Initalized the onion pool which maps cookie address to hidden service
* onion address.
@@ -311,9 +311,14 @@ static void __attribute__((constructor)) tsocks_init(void)
/*
* Lib destructor.
*/
-static void __attribute__((destructor)) tsocks_exit(void)
+static void tsocks_exit(void)
{
- tsocks_cleanup();
+ /* Cleanup every entries in the onion pool. */
+ onion_pool_destroy(&tsocks_onion_pool);
+ /* Cleanup allocated memory in the config file. */
+ config_file_destroy(&tsocks_config.conf_file);
+ /* Clean up logging. */
+ log_destroy();
}
/*
@@ -605,20 +610,17 @@ void *tsocks_find_libc_symbol(const char *symbol,
}
/*
- * Cleanup torsocks library memory and open fd.
+ * Initialize torsocks library.
*/
-void tsocks_cleanup(void)
+void __attribute__((constructor)) tsocks_initialize(void)
{
- if (tsocks_cleaned_up) {
- return;
- }
-
- /* Cleanup every entries in the onion pool. */
- onion_pool_destroy(&tsocks_onion_pool);
- /* Cleanup allocated memory in the config file. */
- config_file_destroy(&tsocks_config.conf_file);
- /* Clean up logging. */
- log_destroy();
+ tsocks_once(&init_once, &tsocks_init);
+}
- tsocks_cleaned_up = 1;
+/*
+ * Cleanup torsocks library memory and open fd.
+ */
+void __attribute__((destructor)) tsocks_cleanup(void)
+{
+ tsocks_once(&term_once, &tsocks_exit);
}
diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h
index 81073cf..076f3a5 100644
--- a/src/lib/torsocks.h
+++ b/src/lib/torsocks.h
@@ -422,6 +422,7 @@ void *tsocks_find_libc_symbol(const char *symbol,
enum tsocks_sym_action action);
int tsocks_tor_resolve(int af, const char *hostname, void *ip_addr);
int tsocks_tor_resolve_ptr(const char *addr, char **ip, int af);
+void tsocks_initialize(void);
void tsocks_cleanup(void);
#endif /* TORSOCKS_H */
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits