diff options
author | zugz (tox) <mbays+tox@sdf.org> | 2018-09-29 10:49:52 +0200 |
---|---|---|
committer | zugz (tox) <mbays+tox@sdf.org> | 2018-10-07 20:13:51 +0200 |
commit | 5beb00c93d3adb5c23149535624d27c67bc146ea (patch) | |
tree | 270dcde41751d421fae86f8f466038c212ed559d /toxcore/TCP_server.c | |
parent | b2b96b1aa19ef2eb2816303e606a3f23550538dc (diff) |
Fix memleak in tcp server by wiping priority queues on deletion
Diffstat (limited to 'toxcore/TCP_server.c')
-rw-r--r-- | toxcore/TCP_server.c | 99 |
1 files changed, 67 insertions, 32 deletions
diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 2b6878fe..23b95940 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c | |||
@@ -124,43 +124,74 @@ size_t tcp_server_listen_count(const TCP_Server *tcp_server) | |||
124 | #endif | 124 | #endif |
125 | #endif | 125 | #endif |
126 | 126 | ||
127 | /* Set the size of the connection list to numfriends. | 127 | /* Increase the size of the connection list |
128 | * | 128 | * |
129 | * return -1 if realloc fails. | 129 | * return -1 on failure |
130 | * return 0 if it succeeds. | 130 | * return 0 on success. |
131 | */ | 131 | */ |
132 | static int realloc_connection(TCP_Server *tcp_server, uint32_t num) | 132 | static int alloc_new_connections(TCP_Server *tcp_server, uint32_t num) |
133 | { | 133 | { |
134 | if (num == 0) { | 134 | const uint32_t new_size = tcp_server->size_accepted_connections + num; |
135 | free(tcp_server->accepted_connection_array); | ||
136 | tcp_server->accepted_connection_array = nullptr; | ||
137 | tcp_server->size_accepted_connections = 0; | ||
138 | return 0; | ||
139 | } | ||
140 | 135 | ||
141 | if (num == tcp_server->size_accepted_connections) { | 136 | if (new_size < tcp_server->size_accepted_connections) { |
142 | return 0; | 137 | return -1; |
143 | } | 138 | } |
144 | 139 | ||
145 | TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)realloc( | 140 | TCP_Secure_Connection *new_connections = (TCP_Secure_Connection *)realloc( |
146 | tcp_server->accepted_connection_array, | 141 | tcp_server->accepted_connection_array, |
147 | num * sizeof(TCP_Secure_Connection)); | 142 | new_size * sizeof(TCP_Secure_Connection)); |
148 | 143 | ||
149 | if (new_connections == nullptr) { | 144 | if (new_connections == nullptr) { |
150 | return -1; | 145 | return -1; |
151 | } | 146 | } |
152 | 147 | ||
153 | if (num > tcp_server->size_accepted_connections) { | 148 | const uint32_t old_size = tcp_server->size_accepted_connections; |
154 | uint32_t old_size = tcp_server->size_accepted_connections; | 149 | const uint32_t size_new_entries = num * sizeof(TCP_Secure_Connection); |
155 | uint32_t size_new_entries = (num - old_size) * sizeof(TCP_Secure_Connection); | 150 | memset(new_connections + old_size, 0, size_new_entries); |
156 | memset(new_connections + old_size, 0, size_new_entries); | ||
157 | } | ||
158 | 151 | ||
159 | tcp_server->accepted_connection_array = new_connections; | 152 | tcp_server->accepted_connection_array = new_connections; |
160 | tcp_server->size_accepted_connections = num; | 153 | tcp_server->size_accepted_connections = new_size; |
161 | return 0; | 154 | return 0; |
162 | } | 155 | } |
163 | 156 | ||
157 | void wipe_priority_list(TCP_Priority_List *p) | ||
158 | { | ||
159 | while (p) { | ||
160 | TCP_Priority_List *pp = p; | ||
161 | p = p->next; | ||
162 | free(pp); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void wipe_secure_connection(TCP_Secure_Connection *con) | ||
167 | { | ||
168 | if (con->status) { | ||
169 | wipe_priority_list(con->priority_queue_start); | ||
170 | crypto_memzero(con, sizeof(TCP_Secure_Connection)); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | static void move_secure_connection(TCP_Secure_Connection *con_new, TCP_Secure_Connection *con_old) | ||
175 | { | ||
176 | memcpy(con_new, con_old, sizeof(TCP_Secure_Connection)); | ||
177 | crypto_memzero(con_old, sizeof(TCP_Secure_Connection)); | ||
178 | } | ||
179 | |||
180 | static void free_accepted_connection_array(TCP_Server *tcp_server) | ||
181 | { | ||
182 | if (tcp_server->accepted_connection_array == nullptr) { | ||
183 | return; | ||
184 | } | ||
185 | |||
186 | for (uint32_t i = 0; i < tcp_server->size_accepted_connections; ++i) { | ||
187 | wipe_secure_connection(&tcp_server->accepted_connection_array[i]); | ||
188 | } | ||
189 | |||
190 | free(tcp_server->accepted_connection_array); | ||
191 | tcp_server->accepted_connection_array = nullptr; | ||
192 | tcp_server->size_accepted_connections = 0; | ||
193 | } | ||
194 | |||
164 | /* return index corresponding to connection with peer on success | 195 | /* return index corresponding to connection with peer on success |
165 | * return -1 on failure. | 196 | * return -1 on failure. |
166 | */ | 197 | */ |
@@ -177,7 +208,7 @@ static int kill_accepted(TCP_Server *tcp_server, int index); | |||
177 | * return index on success | 208 | * return index on success |
178 | * return -1 on failure | 209 | * return -1 on failure |
179 | */ | 210 | */ |
180 | static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, const TCP_Secure_Connection *con) | 211 | static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_Secure_Connection *con) |
181 | { | 212 | { |
182 | int index = get_TCP_connection_index(tcp_server, con->public_key); | 213 | int index = get_TCP_connection_index(tcp_server, con->public_key); |
183 | 214 | ||
@@ -187,7 +218,7 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, cons | |||
187 | } | 218 | } |
188 | 219 | ||
189 | if (tcp_server->size_accepted_connections == tcp_server->num_accepted_connections) { | 220 | if (tcp_server->size_accepted_connections == tcp_server->num_accepted_connections) { |
190 | if (realloc_connection(tcp_server, tcp_server->size_accepted_connections + 4) == -1) { | 221 | if (alloc_new_connections(tcp_server, 4) == -1) { |
191 | return -1; | 222 | return -1; |
192 | } | 223 | } |
193 | 224 | ||
@@ -212,7 +243,8 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, cons | |||
212 | return -1; | 243 | return -1; |
213 | } | 244 | } |
214 | 245 | ||
215 | memcpy(&tcp_server->accepted_connection_array[index], con, sizeof(TCP_Secure_Connection)); | 246 | move_secure_connection(&tcp_server->accepted_connection_array[index], con); |
247 | |||
216 | tcp_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED; | 248 | tcp_server->accepted_connection_array[index].status = TCP_STATUS_CONFIRMED; |
217 | ++tcp_server->num_accepted_connections; | 249 | ++tcp_server->num_accepted_connections; |
218 | tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; | 250 | tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; |
@@ -241,11 +273,11 @@ static int del_accepted(TCP_Server *tcp_server, int index) | |||
241 | return -1; | 273 | return -1; |
242 | } | 274 | } |
243 | 275 | ||
244 | crypto_memzero(&tcp_server->accepted_connection_array[index], sizeof(TCP_Secure_Connection)); | 276 | wipe_secure_connection(&tcp_server->accepted_connection_array[index]); |
245 | --tcp_server->num_accepted_connections; | 277 | --tcp_server->num_accepted_connections; |
246 | 278 | ||
247 | if (tcp_server->num_accepted_connections == 0) { | 279 | if (tcp_server->num_accepted_connections == 0) { |
248 | realloc_connection(tcp_server, 0); | 280 | free_accepted_connection_array(tcp_server); |
249 | } | 281 | } |
250 | 282 | ||
251 | return 0; | 283 | return 0; |
@@ -513,7 +545,7 @@ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, const | |||
513 | static void kill_TCP_secure_connection(TCP_Secure_Connection *con) | 545 | static void kill_TCP_secure_connection(TCP_Secure_Connection *con) |
514 | { | 546 | { |
515 | kill_sock(con->sock); | 547 | kill_sock(con->sock); |
516 | crypto_memzero(con, sizeof(TCP_Secure_Connection)); | 548 | wipe_secure_connection(con); |
517 | } | 549 | } |
518 | 550 | ||
519 | static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *con, uint8_t con_number); | 551 | static int rm_connection_index(TCP_Server *tcp_server, TCP_Secure_Connection *con, uint8_t con_number); |
@@ -965,7 +997,7 @@ static int confirm_TCP_connection(TCP_Server *tcp_server, const Mono_Time *mono_ | |||
965 | return -1; | 997 | return -1; |
966 | } | 998 | } |
967 | 999 | ||
968 | crypto_memzero(con, sizeof(TCP_Secure_Connection)); | 1000 | wipe_secure_connection(con); |
969 | 1001 | ||
970 | if (handle_TCP_packet(tcp_server, index, data, length) == -1) { | 1002 | if (handle_TCP_packet(tcp_server, index, data, length) == -1) { |
971 | kill_accepted(tcp_server, index); | 1003 | kill_accepted(tcp_server, index); |
@@ -1152,8 +1184,7 @@ static int do_incoming(TCP_Server *tcp_server, uint32_t i) | |||
1152 | kill_TCP_secure_connection(conn_new); | 1184 | kill_TCP_secure_connection(conn_new); |
1153 | } | 1185 | } |
1154 | 1186 | ||
1155 | memcpy(conn_new, conn_old, sizeof(TCP_Secure_Connection)); | 1187 | move_secure_connection(conn_new, conn_old); |
1156 | crypto_memzero(conn_old, sizeof(TCP_Secure_Connection)); | ||
1157 | ++tcp_server->unconfirmed_connection_queue_index; | 1188 | ++tcp_server->unconfirmed_connection_queue_index; |
1158 | 1189 | ||
1159 | return index_new; | 1190 | return index_new; |
@@ -1435,9 +1466,7 @@ void do_TCP_server(TCP_Server *tcp_server, Mono_Time *mono_time) | |||
1435 | 1466 | ||
1436 | void kill_TCP_server(TCP_Server *tcp_server) | 1467 | void kill_TCP_server(TCP_Server *tcp_server) |
1437 | { | 1468 | { |
1438 | uint32_t i; | 1469 | for (uint32_t i = 0; i < tcp_server->num_listening_socks; ++i) { |
1439 | |||
1440 | for (i = 0; i < tcp_server->num_listening_socks; ++i) { | ||
1441 | kill_sock(tcp_server->socks_listening[i]); | 1470 | kill_sock(tcp_server->socks_listening[i]); |
1442 | } | 1471 | } |
1443 | 1472 | ||
@@ -1451,7 +1480,13 @@ void kill_TCP_server(TCP_Server *tcp_server) | |||
1451 | close(tcp_server->efd); | 1480 | close(tcp_server->efd); |
1452 | #endif | 1481 | #endif |
1453 | 1482 | ||
1483 | for (uint32_t i = 0; i < MAX_INCOMING_CONNECTIONS; ++i) { | ||
1484 | wipe_secure_connection(&tcp_server->incoming_connection_queue[i]); | ||
1485 | wipe_secure_connection(&tcp_server->unconfirmed_connection_queue[i]); | ||
1486 | } | ||
1487 | |||
1488 | free_accepted_connection_array(tcp_server); | ||
1489 | |||
1454 | free(tcp_server->socks_listening); | 1490 | free(tcp_server->socks_listening); |
1455 | free(tcp_server->accepted_connection_array); | ||
1456 | free(tcp_server); | 1491 | free(tcp_server); |
1457 | } | 1492 | } |