From 3785261a19bc2be523f288ba032f78f0b02bccdd Mon Sep 17 00:00:00 2001 From: laforge Date: Fri, 2 May 2003 15:30:11 +0000 Subject: fix memory leak(s) in libiptc. Reverts the previous (wrong) patch. (Martin Josefsson) --- include/libiptc/libiptc.h | 3 +++ ip6tables-restore.c | 7 +++++-- ip6tables-save.c | 2 ++ ip6tables.c | 8 +++++++- iptables-restore.c | 7 +++++-- iptables-save.c | 2 ++ iptables.c | 8 +++++++- libiptc/libip4tc.c | 1 + libiptc/libip6tc.c | 1 + libiptc/libiptc.c | 44 ++++++++++++++++++++++++++++---------------- 10 files changed, 61 insertions(+), 22 deletions(-) diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index 82745f9..50765d9 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -34,6 +34,9 @@ int iptc_is_chain(const char *chain, const iptc_handle_t handle); /* Take a snapshot of the rules. Returns NULL on error. */ iptc_handle_t iptc_init(const char *tablename); +/* Cleanup after iptc_init(). */ +void iptc_free(iptc_handle_t *h); + /* Iterator functions to run through the chains. Returns NULL at end. */ const char *iptc_first_chain(iptc_handle_t *handle); const char *iptc_next_chain(iptc_handle_t *handle); diff --git a/ip6tables-restore.c b/ip6tables-restore.c index 82e1d2b..ecda870 100644 --- a/ip6tables-restore.c +++ b/ip6tables-restore.c @@ -7,7 +7,7 @@ * Rusty Russell * This code is distributed under the terms of GNU GPL v2 * - * $Id: ip6tables-restore.c,v 1.10 2002/08/14 11:40:41 laforge Exp $ + * $Id: ip6tables-restore.c,v 1.11 2003/03/05 07:46:15 laforge Exp $ */ #include @@ -102,7 +102,7 @@ static void free_argv(void) { int main(int argc, char *argv[]) { - ip6tc_handle_t handle; + ip6tc_handle_t handle = NULL; char buffer[10240]; int c; char curtable[IP6T_TABLE_MAXNAMELEN + 1]; @@ -183,6 +183,9 @@ int main(int argc, char *argv[]) } strncpy(curtable, table, IP6T_TABLE_MAXNAMELEN); + if (handle) + ip6tc_free(&handle); + handle = create_handle(table, modprobe); if (noflush == 0) { DEBUGP("Cleaning all chains of table '%s'\n", diff --git a/ip6tables-save.c b/ip6tables-save.c index b9dbd80..77cc325 100644 --- a/ip6tables-save.c +++ b/ip6tables-save.c @@ -305,6 +305,8 @@ static int do_output(const char *tablename) exit_error(OTHER_PROBLEM, "Binary NYI\n"); } + ip6tc_free(&h); + return 1; } diff --git a/ip6tables.c b/ip6tables.c index 17bdb4e..d250882 100644 --- a/ip6tables.c +++ b/ip6tables.c @@ -1670,6 +1670,7 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle) const char *modprobe = NULL; int proto_used = 0; char icmp6p[] = "icmpv6"; + int no_handle = 0; memset(&fw, 0, sizeof(fw)); @@ -2147,8 +2148,10 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle) chain, IP6T_FUNCTION_MAXNAMELEN); /* only allocate handle if we weren't called with a handle */ - if (!*handle) + if (!*handle) { *handle = ip6tc_init(*table); + no_handle = 1; + } if (!*handle) { /* try to insmod the module if iptc_init failed */ @@ -2293,5 +2296,8 @@ int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t *handle) if (verbose > 1) dump_entries6(*handle); + if (no_handle) + ip6tc_free(handle); + return ret; } diff --git a/iptables-restore.c b/iptables-restore.c index 74f7db3..c1888ce 100644 --- a/iptables-restore.c +++ b/iptables-restore.c @@ -4,7 +4,7 @@ * * This code is distributed under the terms of GNU GPL v2 * - * $Id: iptables-restore.c,v 1.24 2003/03/03 08:08:37 laforge Exp $ + * $Id: iptables-restore.c,v 1.25 2003/03/06 11:56:31 laforge Exp $ */ #include @@ -99,7 +99,7 @@ static void free_argv(void) { int main(int argc, char *argv[]) { - iptc_handle_t handle; + iptc_handle_t handle = NULL; char buffer[10240]; int c; char curtable[IPT_TABLE_MAXNAMELEN + 1]; @@ -180,6 +180,9 @@ int main(int argc, char *argv[]) } strncpy(curtable, table, IPT_TABLE_MAXNAMELEN); + if (handle) + iptc_free(&handle); + handle = create_handle(table, modprobe); if (noflush == 0) { DEBUGP("Cleaning all chains of table '%s'\n", diff --git a/iptables-save.c b/iptables-save.c index 74e71ff..90163b5 100644 --- a/iptables-save.c +++ b/iptables-save.c @@ -304,6 +304,8 @@ static int do_output(const char *tablename) exit_error(OTHER_PROBLEM, "Binary NYI\n"); } + iptc_free(&h); + return 1; } diff --git a/iptables.c b/iptables.c index a3bcc78..d181578 100644 --- a/iptables.c +++ b/iptables.c @@ -1668,6 +1668,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) char *protocol = NULL; const char *modprobe = NULL; int proto_used = 0; + int no_handle = 0; memset(&fw, 0, sizeof(fw)); @@ -2148,8 +2149,10 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) chain, IPT_FUNCTION_MAXNAMELEN); /* only allocate handle if we weren't called with a handle */ - if (!*handle) + if (!*handle) { *handle = iptc_init(*table); + no_handle = 1; + } if (!*handle) { /* try to insmod the module if iptc_init failed */ @@ -2294,5 +2297,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle) if (verbose > 1) dump_entries(*handle); + if (no_handle) + iptc_free(handle); + return ret; } diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c index e15df90..e012c08 100644 --- a/libiptc/libip4tc.c +++ b/libiptc/libip4tc.c @@ -91,6 +91,7 @@ typedef unsigned int socklen_t; #define TC_SET_POLICY iptc_set_policy #define TC_GET_RAW_SOCKET iptc_get_raw_socket #define TC_INIT iptc_init +#define TC_FREE iptc_free #define TC_COMMIT iptc_commit #define TC_STRERROR iptc_strerror diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index 7a88efd..84e139c 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -86,6 +86,7 @@ typedef unsigned int socklen_t; #define TC_SET_POLICY ip6tc_set_policy #define TC_GET_RAW_SOCKET ip6tc_get_raw_socket #define TC_INIT ip6tc_init +#define TC_FREE ip6tc_free #define TC_COMMIT ip6tc_commit #define TC_STRERROR ip6tc_strerror diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index 55b708b..fa73563 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -1,4 +1,4 @@ -/* Library which manipulates firewall rules. Version $Revision: 1.35 $ */ +/* Library which manipulates firewall rules. Version $Revision: 1.36 $ */ /* Architecture of firewall rules is as follows: * @@ -237,22 +237,26 @@ TC_INIT(const char *tablename) if (sockfd != -1) close(sockfd); + if (strlen(tablename) >= TABLE_MAXNAMELEN) { + errno = EINVAL; + return NULL; + } + sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); if (sockfd < 0) return NULL; s = sizeof(info); - if (strlen(tablename) >= TABLE_MAXNAMELEN) { - errno = EINVAL; - return NULL; - } + strcpy(info.name, tablename); if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) return NULL; if ((h = alloc_handle(info.name, info.size, info.num_entries)) - == NULL) + == NULL) { + close(sockfd); return NULL; + } /* Too hard --RR */ #if 0 @@ -284,6 +288,7 @@ TC_INIT(const char *tablename) if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, &h->entries, &tmp) < 0) { + close(sockfd); free(h); return NULL; } @@ -292,6 +297,16 @@ TC_INIT(const char *tablename) return h; } +void +TC_FREE(TC_HANDLE_T *h) +{ + close(sockfd); + if ((*h)->cache_chain_heads) + free((*h)->cache_chain_heads); + free(*h); + *h = NULL; +} + static inline int print_match(const STRUCT_ENTRY_MATCH *m) { @@ -504,10 +519,8 @@ TC_NEXT_CHAIN(TC_HANDLE_T *handle) (*handle)->cache_chain_iteration++; if ((*handle)->cache_chain_iteration - (*handle)->cache_chain_heads - == (*handle)->cache_num_chains) { - free((*handle)->cache_chain_heads); + == (*handle)->cache_num_chains) return NULL; - } return (*handle)->cache_chain_iteration->name; } @@ -1584,11 +1597,13 @@ TC_COMMIT(TC_HANDLE_T *handle) STRUCT_REPLACE *repl; STRUCT_COUNTERS_INFO *newcounters; unsigned int i; - size_t counterlen - = sizeof(STRUCT_COUNTERS_INFO) - + sizeof(STRUCT_COUNTERS) * (*handle)->new_number; + size_t counterlen; CHECK(*handle); + + counterlen = sizeof(STRUCT_COUNTERS_INFO) + + sizeof(STRUCT_COUNTERS) * (*handle)->new_number; + #if 0 TC_DUMP_ENTRIES(*handle); #endif @@ -1715,10 +1730,7 @@ TC_COMMIT(TC_HANDLE_T *handle) free(newcounters); finished: - if ((*handle)->cache_chain_heads) - free((*handle)->cache_chain_heads); - free(*handle); - *handle = NULL; + TC_FREE(handle); return 1; } -- cgit v1.2.3