From 7ab400aebdc38e7ee5dafc0a2291bbbea25e3f7c Mon Sep 17 00:00:00 2001 From: Kirill Isakov Date: Sun, 25 Jul 2021 17:15:24 +0600 Subject: [PATCH] Fix more memory leaks found by ASAN. --- src/address_cache.c | 1 + src/fsck.c | 37 +++++++++++++++++++-- src/invitation.c | 1 + src/net_setup.c | 79 +++++++++++++++++++++++++++++++++------------ src/net_socket.c | 2 ++ src/protocol_auth.c | 3 ++ src/tincctl.c | 2 +- test/splice.c | 19 +++++++---- 8 files changed, 113 insertions(+), 31 deletions(-) diff --git a/src/address_cache.c b/src/address_cache.c index b6d48d02..df465da3 100644 --- a/src/address_cache.c +++ b/src/address_cache.c @@ -67,6 +67,7 @@ static struct addrinfo *get_known_addresses(node_t *n) { static void free_known_addresses(struct addrinfo *ai) { for(struct addrinfo *aip = ai, *next; aip; aip = next) { next = aip->ai_next; + free(aip->ai_addr); free(aip); } } diff --git a/src/fsck.c b/src/fsck.c index a60dcf3f..f10fe3c4 100644 --- a/src/fsck.c +++ b/src/fsck.c @@ -234,6 +234,7 @@ int fsck(const char *argv0) { // Something is seriously wrong here. If we can access the directory with tinc.conf in it, we should certainly be able to stat() an existing file. fprintf(stderr, "ERROR: cannot read %s: %s\n", fname, strerror(errno)); fprintf(stderr, "Please correct this error.\n"); + free(name); return 1; } } else { @@ -241,6 +242,7 @@ int fsck(const char *argv0) { if(!f) { fprintf(stderr, "ERROR: could not open %s: %s\n", fname, strerror(errno)); + free(name); return 1; } @@ -251,6 +253,7 @@ int fsck(const char *argv0) { fprintf(stderr, "ERROR: No key or unusable key found in %s.\n", fname); fprintf(stderr, "You can generate a new RSA key with:\n\n"); print_tinc_cmd(argv0, "generate-rsa-keys"); + free(name); return 1; } @@ -283,6 +286,7 @@ int fsck(const char *argv0) { // Something is seriously wrong here. If we can access the directory with tinc.conf in it, we should certainly be able to stat() an existing file. fprintf(stderr, "ERROR: cannot read %s: %s\n", fname, strerror(errno)); fprintf(stderr, "Please correct this error.\n"); + free(name); return 1; } } else { @@ -290,6 +294,7 @@ int fsck(const char *argv0) { if(!f) { fprintf(stderr, "ERROR: could not open %s: %s\n", fname, strerror(errno)); + free(name); return 1; } @@ -300,6 +305,7 @@ int fsck(const char *argv0) { fprintf(stderr, "ERROR: No key or unusable key found in %s.\n", fname); fprintf(stderr, "You can generate a new Ed25519 key with:\n\n"); print_tinc_cmd(argv0, "generate-ed25519-keys"); + free(name); return 1; } @@ -333,6 +339,7 @@ int fsck(const char *argv0) { #endif fprintf(stderr, "You can generate new keys with:\n\n"); print_tinc_cmd(argv0, "generate-keys"); + free(name); return 1; } @@ -341,6 +348,8 @@ int fsck(const char *argv0) { snprintf(fname, sizeof(fname), "%s/hosts/%s", confbase, name); + free(name); + if(access(fname, R_OK)) { fprintf(stderr, "WARNING: cannot read %s\n", fname); } @@ -382,6 +391,9 @@ int fsck(const char *argv0) { if(len != rsa_size(rsa_pub)) { fprintf(stderr, "ERROR: public and private RSA keys do not match.\n"); + rsa_free(rsa_pub); + rsa_free(rsa_priv); + free(ecdsa_priv); return 1; } @@ -409,18 +421,28 @@ int fsck(const char *argv0) { fprintf(stderr, "ERROR: public RSA key does not work.\n"); } + + rsa_free(rsa_pub); + rsa_pub = NULL; + free(buf3); free(buf2); free(buf1); if(!result) { + rsa_free(rsa_priv); + free(ecdsa_priv); return 1; } - } + + rsa_free(rsa_priv); + rsa_priv = NULL; } else { if(rsa_pub) { fprintf(stderr, "WARNING: A public RSA key was found but no private key is known.\n"); + rsa_free(rsa_pub); + rsa_pub = NULL; } } @@ -464,16 +486,21 @@ int fsck(const char *argv0) { // TODO: suggest remedies char *key1 = ecdsa_get_base64_public_key(ecdsa_pub); + free(ecdsa_pub); + ecdsa_pub = NULL; + if(!key1) { fprintf(stderr, "ERROR: public Ed25519 key does not work.\n"); + free(ecdsa_priv); return 1; } char *key2 = ecdsa_get_base64_public_key(ecdsa_priv); if(!key2) { - free(key1); fprintf(stderr, "ERROR: private Ed25519 key does not work.\n"); + free(ecdsa_priv); + free(key1); return 1; } @@ -483,12 +510,18 @@ int fsck(const char *argv0) { if(result) { fprintf(stderr, "ERROR: public and private Ed25519 keys do not match.\n"); + free(ecdsa_priv); return 1; } } + + free(ecdsa_priv); + ecdsa_priv = NULL; } else { if(ecdsa_pub) { fprintf(stderr, "WARNING: A public Ed25519 key was found but no private key is known.\n"); + free(ecdsa_pub); + ecdsa_pub = NULL; } } diff --git a/src/invitation.c b/src/invitation.c index d615976d..b2e35f98 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -292,6 +292,7 @@ int cmd_invite(int argc, char *argv[]) { return 1; } + free(myname); myname = get_my_name(true); if(!myname) { diff --git a/src/net_setup.c b/src/net_setup.c index a04f9535..d4bc59e5 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -52,10 +52,11 @@ static io_t device_io; devops_t devops; bool device_standby = false; -char *proxyhost; -char *proxyport; -char *proxyuser; -char *proxypass; +char *proxyhost = NULL; +char *proxyport = NULL; +char *proxyuser = NULL; +char *proxypass = NULL; + proxytype_t proxytype; bool autoconnect; bool disablebuggypeers; @@ -435,18 +436,10 @@ char *get_name(void) { } bool setup_myself_reloadable(void) { - char *proxy = NULL; - char *rmode = NULL; - char *fmode = NULL; - char *bmode = NULL; - char *afname = NULL; - char *space; - bool choice; - free(scriptinterpreter); scriptinterpreter = NULL; - get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter); + get_config_string(lookup_config(config_tree, "ScriptsInterpreter"), &scriptinterpreter); free(scriptextension); @@ -454,9 +447,13 @@ bool setup_myself_reloadable(void) { scriptextension = xstrdup(""); } + char *proxy = NULL; + get_config_string(lookup_config(config_tree, "Proxy"), &proxy); if(proxy) { + char *space; + if((space = strchr(proxy, ' '))) { *space++ = 0; } @@ -475,9 +472,22 @@ bool setup_myself_reloadable(void) { proxytype = PROXY_EXEC; } else { logger(DEBUG_ALWAYS, LOG_ERR, "Unknown proxy type %s!", proxy); + free(proxy); return false; } + free(proxyhost); + proxyhost = NULL; + + free(proxyport); + proxyport = NULL; + + free(proxyuser); + proxyuser = NULL; + + free(proxypass); + proxypass = NULL; + switch(proxytype) { case PROXY_NONE: default: @@ -486,10 +496,11 @@ bool setup_myself_reloadable(void) { case PROXY_EXEC: if(!space || !*space) { logger(DEBUG_ALWAYS, LOG_ERR, "Argument expected for proxy type exec!"); + free(proxy); return false; } - proxyhost = xstrdup(space); + proxyhost = xstrdup(space); break; case PROXY_SOCKS4: @@ -502,6 +513,14 @@ bool setup_myself_reloadable(void) { *space++ = 0, proxyport = space; } + if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) { + logger(DEBUG_ALWAYS, LOG_ERR, "Host and port argument expected for proxy!"); + proxyport = NULL; + proxyhost = NULL; + free(proxy); + return false; + } + if(space && (space = strchr(space, ' '))) { *space++ = 0, proxyuser = space; } @@ -510,11 +529,6 @@ bool setup_myself_reloadable(void) { *space++ = 0, proxypass = space; } - if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) { - logger(DEBUG_ALWAYS, LOG_ERR, "Host and port argument expected for proxy!"); - return false; - } - proxyhost = xstrdup(proxyhost); proxyport = xstrdup(proxyport); @@ -532,6 +546,8 @@ bool setup_myself_reloadable(void) { free(proxy); } + bool choice; + if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) { myself->options |= OPTION_INDIRECT; } @@ -555,6 +571,8 @@ bool setup_myself_reloadable(void) { get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly); get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery); + char *rmode = NULL; + if(get_config_string(lookup_config(config_tree, "Mode"), &rmode)) { if(!strcasecmp(rmode, "router")) { routing_mode = RMODE_ROUTER; @@ -564,12 +582,15 @@ bool setup_myself_reloadable(void) { routing_mode = RMODE_HUB; } else { logger(DEBUG_ALWAYS, LOG_ERR, "Invalid routing mode!"); + free(rmode); return false; } free(rmode); } + char *fmode = NULL; + if(get_config_string(lookup_config(config_tree, "Forwarding"), &fmode)) { if(!strcasecmp(fmode, "off")) { forwarding_mode = FMODE_OFF; @@ -579,6 +600,7 @@ bool setup_myself_reloadable(void) { forwarding_mode = FMODE_KERNEL; } else { logger(DEBUG_ALWAYS, LOG_ERR, "Invalid forwarding mode!"); + free(fmode); return false; } @@ -602,6 +624,8 @@ bool setup_myself_reloadable(void) { get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl); + char *bmode = NULL; + if(get_config_string(lookup_config(config_tree, "Broadcast"), &bmode)) { if(!strcasecmp(bmode, "no")) { broadcast_mode = BMODE_NONE; @@ -611,6 +635,7 @@ bool setup_myself_reloadable(void) { broadcast_mode = BMODE_DIRECT; } else { logger(DEBUG_ALWAYS, LOG_ERR, "Invalid broadcast mode!"); + free(bmode); return false; } @@ -626,7 +651,11 @@ bool setup_myself_reloadable(void) { abort(); } - subnet_add(NULL, s); + if(splay_search(subnet_tree, s)) { + free(s); + } else { + subnet_add(NULL, s); + } } for(config_t *cfg = lookup_config(config_tree, "BroadcastSubnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) { @@ -636,7 +665,11 @@ bool setup_myself_reloadable(void) { continue; } - subnet_add(NULL, s); + if(splay_search(subnet_tree, s)) { + free(s); + } else { + subnet_add(NULL, s); + } } #if !defined(IP_TOS) @@ -668,6 +701,8 @@ bool setup_myself_reloadable(void) { maxtimeout = 900; } + char *afname = NULL; + if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) { if(!strcasecmp(afname, "IPv4")) { addressfamily = AF_INET; @@ -677,6 +712,7 @@ bool setup_myself_reloadable(void) { addressfamily = AF_UNSPEC; } else { logger(DEBUG_ALWAYS, LOG_ERR, "Invalid address family!"); + free(afname); return false; } @@ -762,6 +798,7 @@ static bool add_listen_address(char *address, bool bindto) { if(listen_sockets >= MAXSOCKETS) { logger(DEBUG_ALWAYS, LOG_ERR, "Too many listening sockets"); + freeaddrinfo(ai); return false; } diff --git a/src/net_socket.c b/src/net_socket.c index 05ee3b17..91f0bbb7 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -866,6 +866,8 @@ void try_outgoing_connections(void) { node_add(n); } + free(name); + outgoing->node = n; list_insert_tail(outgoing_list, outgoing); setup_outgoing_connection(outgoing, true); diff --git a/src/protocol_auth.c b/src/protocol_auth.c index a270ffcd..de3d70dd 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -214,6 +214,9 @@ static bool finalize_invitation(connection_t *c, const char *data, uint16_t len) environment_add(&env, "REMOTEADDRESS=%s", address); environment_add(&env, "NAME=%s", myself->name); + free(address); + free(port); + execute_script("invitation-accepted", &env); environment_exit(&env); diff --git a/src/tincctl.c b/src/tincctl.c index 57c42812..ec434696 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -1884,7 +1884,7 @@ static int cmd_config(int argc, char *argv[]) { char *node = NULL; char *variable; char *value; - int len; + size_t len; len = strcspn(line, "\t ="); value = line + len; diff --git a/test/splice.c b/test/splice.c index 31d071c9..118d0118 100644 --- a/test/splice.c +++ b/test/splice.c @@ -70,15 +70,16 @@ int main(int argc, char *argv[]) { int sock[2]; char buf[1024]; - struct addrinfo *ai, hint; - memset(&hint, 0, sizeof(hint)); - - hint.ai_family = AF_UNSPEC; - hint.ai_socktype = SOCK_STREAM; - hint.ai_protocol = IPPROTO_TCP; - hint.ai_flags = 0; + const struct addrinfo hint = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + .ai_flags = 0, + }; for(int i = 0; i < 2; i++) { + struct addrinfo *ai; + if(getaddrinfo(argv[2 + 3 * i], argv[3 + 3 * i], &hint, &ai) || !ai) { fprintf(stderr, "getaddrinfo() failed: %s\n", sockstrerror(sockerrno)); return 1; @@ -88,14 +89,18 @@ int main(int argc, char *argv[]) { if(sock[i] == -1) { fprintf(stderr, "Could not create socket: %s\n", sockstrerror(sockerrno)); + freeaddrinfo(ai); return 1; } if(connect(sock[i], ai->ai_addr, ai->ai_addrlen)) { fprintf(stderr, "Could not connect to %s: %s\n", argv[i + 3 * i], sockstrerror(sockerrno)); + freeaddrinfo(ai); return 1; } + freeaddrinfo(ai); + fprintf(stderr, "Connected to %s\n", argv[1 + 3 * i]); /* Pretend to be the other one */ -- 2.20.1