All of lore.kernel.org
 help / color / mirror / Atom feed
* [IPTABLES PATCH] Fix leak in merge_opts
@ 2005-05-07 14:26 Pablo Neira
  2005-05-29 18:55 ` Harald Welte
  0 siblings, 1 reply; 2+ messages in thread
From: Pablo Neira @ 2005-05-07 14:26 UTC (permalink / raw)
  To: Netfilter Development Mailinglist; +Cc: Harald Welte

[-- Attachment #1: Type: text/plain, Size: 481 bytes --]

Hi Harald,

The function merge_opts doesn't release previously merged options, this 
results in a memory leak. This increases considerably memory comsumption 
in iptables-restore.

This patch fixes a leak on error paths as well.

Results: With my testcase ruleset of ~10.000 rules and this patch, 
iptables-restore reduces memory consumption by 66 percent. It's passed 
from eating ~12 Mbytes to ~4 Mbytes. This can be interesting for 
embedded devices running iptables.

--
Pablo

[-- Attachment #2: x --]
[-- Type: text/plain, Size: 2730 bytes --]

Index: iptables.c
===================================================================
--- iptables.c	(revision 3889)
+++ iptables.c	(working copy)
@@ -306,6 +306,16 @@
 	dst->s_addr = src->s_addr;
 }
 
+static void free_opts(int reset_offset)
+{
+	if (opts != original_opts) {
+		free(opts);
+		opts = original_opts;
+		if (reset_offset)
+			global_option_offset = 0;
+	}
+}
+
 void
 exit_error(enum exittype status, char *msg, ...)
 {
@@ -321,6 +331,8 @@
 	if (status == VERSION_PROBLEM)
 		fprintf(stderr,
 			"Perhaps iptables or your kernel needs to be upgraded.\n");
+	/* On error paths, make sure that we don't leak memory */
+	free_opts(1);
 	exit(status);
 }
 
@@ -331,6 +343,7 @@
 		fprintf(stderr, "Error occurred at line: %d\n", line);
 	fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
 			program_name, program_name );
+	free_opts(1);
 	exit(status);
 }
 
@@ -1016,6 +1029,9 @@
 	unsigned int num_old, num_new, i;
 	struct option *merge;
 
+	/* Release previous options merged if any */
+	free_opts(0);
+	
 	for (num_old = 0; oldopts[num_old].name; num_old++);
 	for (num_new = 0; newopts[num_new].name; num_new++);
 
@@ -2443,12 +2459,7 @@
 
 	free(saddrs);
 	free(daddrs);
+	free_opts(1);
 
-	if (opts != original_opts) {
-		free(opts);
-		opts = original_opts;
-		global_option_offset = 0;
-	}
-
 	return ret;
 }
Index: ip6tables.c
===================================================================
--- ip6tables.c	(revision 3889)
+++ ip6tables.c	(working copy)
@@ -252,6 +252,16 @@
 	/* dst->s6_addr = src->s6_addr; */
 }
 
+static void free_opts(int reset_offset)
+{
+	if (opts != original_opts) {
+		free(opts);
+		opts = original_opts;
+		if (reset_offset)
+			global_option_offset = 0;
+	}
+}
+
 void
 exit_error(enum exittype status, char *msg, ...)
 {
@@ -267,6 +277,8 @@
 	if (status == VERSION_PROBLEM)
 		fprintf(stderr,
 			"Perhaps ip6tables or your kernel needs to be upgraded.\n");
+	/* On error paths, make sure that we don't leak memory */
+	free_opts(1);
 	exit(status);
 }
 
@@ -277,6 +289,7 @@
 		fprintf(stderr, "Error occurred at line: %d\n", line);
 	fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
 			program_name, program_name );
+	free_opts(1);
 	exit(status);
 }
 
@@ -1016,6 +1029,9 @@
 	unsigned int num_old, num_new, i;
 	struct option *merge;
 
+	/* Release previous options merged if any */
+	free_opts(0);
+
 	for (num_old = 0; oldopts[num_old].name; num_old++);
 	for (num_new = 0; newopts[num_new].name; num_new++);
 
@@ -2336,11 +2352,7 @@
 	for (c = 0; c < ndaddrs; c++)
 		free(&daddrs[c]);
 
-	if (opts != original_opts) {
-		free(opts);
-		opts = original_opts;
-		global_option_offset = 0;
-	}
+	free_opts(1);
 
 	return ret;
 }

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-05-29 18:55 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-07 14:26 [IPTABLES PATCH] Fix leak in merge_opts Pablo Neira
2005-05-29 18:55 ` Harald Welte

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.