From 85bc53cbd137ff40e11bfaa6201b48a516ed5100 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Fri, 26 Jun 2020 10:51:01 +0200 Subject: [PATCH] Bind to socket in thread instead of main process to ensure forks do not inherit sockets they shouldn't. Signed-off-by: DL6ER --- src/api/socket.c | 47 ++++++++++++++++++----------------------- src/dnsmasq/dnsmasq.c | 2 ++ src/dnsmasq_interface.c | 17 ++++++++++----- src/dnsmasq_interface.h | 1 + 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/api/socket.c b/src/api/socket.c index 34c45237..e471c750 100644 --- a/src/api/socket.c +++ b/src/api/socket.c @@ -31,8 +31,7 @@ // File descriptors int socketfd, telnetfd4 = 0, telnetfd6 = 0; bool dualstack = false; -bool ipv4telnet = false, ipv6telnet = false; -bool sock_avail = false; +bool ipv4telnet = false, ipv6telnet = false, sock_avail = false; bool istelnet[MAXCONNS]; static void saveport(void) @@ -95,6 +94,7 @@ static bool bind_to_telnet_port_IPv4(int *socketdescriptor) return false; } + saveport(); logg("Listening on port %i for incoming IPv4 telnet connections", config.port); return true; } @@ -157,11 +157,12 @@ static bool bind_to_telnet_port_IPv6(int *socketdescriptor) return false; } + saveport(); logg("Listening on port %i for incoming IPv6 telnet connections", config.port); return true; } -static void bind_to_unix_socket(int *socketdescriptor) +static bool bind_to_unix_socket(int *socketdescriptor) { *socketdescriptor = socket(AF_LOCAL, SOCK_STREAM, 0); @@ -169,7 +170,7 @@ static void bind_to_unix_socket(int *socketdescriptor) { logg("WARNING: Error opening Unix socket."); logg(" Continuing anyway."); - return; + return false; } // Make sure unix socket file handle does not exist, if it exists, remove it @@ -191,7 +192,7 @@ static void bind_to_unix_socket(int *socketdescriptor) { logg("WARNING: Cannot bind on Unix socket %s: %s (%i)", FTLfiles.socketfile, strerror(errno), errno); logg(" Continuing anyway."); - return; + return false; } // The listen system call allows the process to listen on the Unix socket for connections @@ -199,11 +200,11 @@ static void bind_to_unix_socket(int *socketdescriptor) { logg("WARNING: Cannot listen on Unix socket: %s (%i)", strerror(errno), errno); logg(" Continuing anyway."); - return; + return false; } logg("Listening on Unix socket"); - sock_avail = true; + return true; } // Called from main() at graceful shutdown @@ -413,24 +414,6 @@ static void *socket_connection_handler_thread(void *socket_desc) return false; } -void bind_sockets(void) -{ - // Initialize IPv4 telnet socket - if(bind_to_telnet_port_IPv4(&telnetfd4)) - ipv4telnet = true; - - // Initialize IPv6 telnet socket - // only if IPv6 interfaces are available - if(ipv6_available()) - if(bind_to_telnet_port_IPv6(&telnetfd6)) - ipv6telnet = true; - - saveport(); - - // Initialize Unix socket - bind_to_unix_socket(&socketfd); -} - void *telnet_listening_thread_IPv4(void *args) { // We will use the attributes object later to start all threads in detached mode @@ -444,6 +427,11 @@ void *telnet_listening_thread_IPv4(void *args) // Set thread name prctl(PR_SET_NAME,"telnet-IPv4",0,0,0); + // Initialize IPv4 telnet socket + if(!bind_to_telnet_port_IPv4(&telnetfd4)) + return NULL; + ipv4telnet = true; + // Listen as long as FTL is not killed while(!killed) { @@ -485,6 +473,12 @@ void *telnet_listening_thread_IPv6(void *args) // Set thread name prctl(PR_SET_NAME,"telnet-IPv6",0,0,0); + // Initialize IPv6 telnet socket + // only if IPv6 interfaces are available + if(!ipv6_available() || !bind_to_telnet_port_IPv6(&telnetfd6)) + return NULL; + ipv6telnet = true; + // Listen as long as FTL is not killed while(!killed) { @@ -527,8 +521,9 @@ void *socket_listening_thread(void *args) prctl(PR_SET_NAME,"socket listener",0,0,0); // Return early to avoid CPU spinning if Unix socket is not available - if(!sock_avail) + if(!bind_to_unix_socket(&socketfd)) return NULL; + sock_avail = true; // Listen as long as FTL is not killed while(!killed) diff --git a/src/dnsmasq/dnsmasq.c b/src/dnsmasq/dnsmasq.c index 9ef0ae6f..1b887053 100644 --- a/src/dnsmasq/dnsmasq.c +++ b/src/dnsmasq/dnsmasq.c @@ -1910,6 +1910,8 @@ static void check_dns_listeners(time_t now) } close(confd); + FTL_TCP_worker_created(); + /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */ daemon->log_id += TCP_MAX_QUERIES; } diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index 379999ae..3512dc29 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -1646,18 +1646,15 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw) // join with the terminated thread pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - // Bind to sockets - bind_sockets(); - // Start TELNET IPv4 thread - if(ipv4telnet && pthread_create( &telnet_listenthreadv4, &attr, telnet_listening_thread_IPv4, NULL ) != 0) + if(pthread_create( &telnet_listenthreadv4, &attr, telnet_listening_thread_IPv4, NULL ) != 0) { logg("Unable to open IPv4 telnet listening thread. Exiting..."); exit(EXIT_FAILURE); } // Start TELNET IPv6 thread - if(ipv6telnet && pthread_create( &telnet_listenthreadv6, &attr, telnet_listening_thread_IPv6, NULL ) != 0) + if(pthread_create( &telnet_listenthreadv6, &attr, telnet_listening_thread_IPv6, NULL ) != 0) { logg("Unable to open IPv6 telnet listening thread. Exiting..."); exit(EXIT_FAILURE); @@ -1832,3 +1829,13 @@ void FTL_TCP_worker_terminating(void) // Close dedicated database connection of this fork gravityDB_close(); } + +// Called when a (forked) TCP worker is created +void FTL_TCP_worker_created(void) +{ + if(config.debug != 0) + { + // Print this if any debug setting is enabled + logg("TCP worker forked"); + } +} diff --git a/src/dnsmasq_interface.h b/src/dnsmasq_interface.h index ab4c77fc..af4d776f 100644 --- a/src/dnsmasq_interface.h +++ b/src/dnsmasq_interface.h @@ -51,6 +51,7 @@ bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const void FTL_dnsmasq_reload(void); void FTL_fork_and_bind_sockets(struct passwd *ent_pw); +void FTL_TCP_worker_created(void); void FTL_TCP_worker_terminating(void); void set_debug_dnsmasq_lines(char enabled);