* [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
@ 2012-07-23 10:38 pablo
2012-07-23 11:29 ` Eric Dumazet
2012-07-23 12:19 ` Jan Engelhardt
0 siblings, 2 replies; 11+ messages in thread
From: pablo @ 2012-07-23 10:38 UTC (permalink / raw)
To: netfilter-devel; +Cc: netfilter
From: Pablo Neira Ayuso <pablo@netfilter.org>
This patch seems to be a mere cleanup that moves the parameter parsing
code to add_param_to_argv.
But, in reality, it also fixes iptables whe compiled with gcc-4.7.
Moving param_buffer declaration out of the loop seems to resolve the
issue. gcc-4.7 seems to be generating bad code regarding param_buffer.
@@ -380,9 +380,9 @@
quote_open = 0;
escaped = 0;
param_len = 0;
+ char param_buffer[1024];
for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
if (quote_open) {
if (escaped) {
But I have hard time to apply this patch in such a way. Instead, I came
up with the idea of this cleanup, which does not harm after all (and fixes
the issue for us).
Sorry, I didn't have the time to further debug this issue, but it would be
worth to investigate what's going wrong and ping gcc people.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
iptables/ip6tables-restore.c | 133 +++++++++++++++++++++---------------------
iptables/iptables-restore.c | 133 +++++++++++++++++++++---------------------
2 files changed, 130 insertions(+), 136 deletions(-)
diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c
index 3894d68..9a03dff 100644
--- a/iptables/ip6tables-restore.c
+++ b/iptables/ip6tables-restore.c
@@ -114,6 +114,70 @@ static void free_argv(void) {
free(newargv[i]);
}
+static void add_param_to_argv(char *parsestart)
+{
+ int quote_open = 0, escaped = 0, param_len = 0;
+ char param_buffer[1024], *curchar;
+
+ /* After fighting with strtok enough, here's now
+ * a 'real' parser. According to Rusty I'm now no
+ * longer a real hacker, but I can live with that */
+
+ for (curchar = parsestart; *curchar; curchar++) {
+ if (quote_open) {
+ if (escaped) {
+ param_buffer[param_len++] = *curchar;
+ escaped = 0;
+ continue;
+ } else if (*curchar == '\\') {
+ escaped = 1;
+ continue;
+ } else if (*curchar == '"') {
+ quote_open = 0;
+ *curchar = ' ';
+ } else {
+ param_buffer[param_len++] = *curchar;
+ continue;
+ }
+ } else {
+ if (*curchar == '"') {
+ quote_open = 1;
+ continue;
+ }
+ }
+
+ if (*curchar == ' '
+ || *curchar == '\t'
+ || * curchar == '\n') {
+ if (!param_len) {
+ /* two spaces? */
+ continue;
+ }
+
+ param_buffer[param_len] = '\0';
+
+ /* check if table name specified */
+ if (!strncmp(param_buffer, "-t", 2)
+ || !strncmp(param_buffer, "--table", 8)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Line %u seems to have a "
+ "-t table option.\n", line);
+ exit(1);
+ }
+
+ add_argv(param_buffer);
+ param_len = 0;
+ } else {
+ /* regular character, copy to buffer */
+ param_buffer[param_len++] = *curchar;
+
+ if (param_len >= sizeof(param_buffer))
+ xtables_error(PARAMETER_PROBLEM,
+ "Parameter too long!");
+ }
+ }
+}
+
int ip6tables_restore_main(int argc, char *argv[])
{
struct xtc_handle *handle = NULL;
@@ -325,11 +389,6 @@ int ip6tables_restore_main(int argc, char *argv[])
char *bcnt = NULL;
char *parsestart;
- /* the parser */
- char *curchar;
- int quote_open, escaped;
- size_t param_len;
-
/* reset the newargv */
newargc = 0;
@@ -370,69 +429,7 @@ int ip6tables_restore_main(int argc, char *argv[])
add_argv((char *) bcnt);
}
- /* After fighting with strtok enough, here's now
- * a 'real' parser. According to Rusty I'm now no
- * longer a real hacker, but I can live with that */
-
- quote_open = 0;
- escaped = 0;
- param_len = 0;
-
- for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
- if (quote_open) {
- if (escaped) {
- param_buffer[param_len++] = *curchar;
- escaped = 0;
- continue;
- } else if (*curchar == '\\') {
- escaped = 1;
- continue;
- } else if (*curchar == '"') {
- quote_open = 0;
- *curchar = ' ';
- } else {
- param_buffer[param_len++] = *curchar;
- continue;
- }
- } else {
- if (*curchar == '"') {
- quote_open = 1;
- continue;
- }
- }
-
- if (*curchar == ' '
- || *curchar == '\t'
- || * curchar == '\n') {
- if (!param_len) {
- /* two spaces? */
- continue;
- }
-
- param_buffer[param_len] = '\0';
-
- /* check if table name specified */
- if (!strncmp(param_buffer, "-t", 2)
- || !strncmp(param_buffer, "--table", 8)) {
- xtables_error(PARAMETER_PROBLEM,
- "Line %u seems to have a "
- "-t table option.\n", line);
- exit(1);
- }
-
- add_argv(param_buffer);
- param_len = 0;
- } else {
- /* regular character, copy to buffer */
- param_buffer[param_len++] = *curchar;
-
- if (param_len >= sizeof(param_buffer))
- xtables_error(PARAMETER_PROBLEM,
- "Parameter too long!");
- }
- }
+ add_param_to_argv(parsestart);
DEBUGP("calling do_command6(%u, argv, &%s, handle):\n",
newargc, curtable);
diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c
index 034f960..c974cb3 100644
--- a/iptables/iptables-restore.c
+++ b/iptables/iptables-restore.c
@@ -113,6 +113,70 @@ static void free_argv(void) {
free(newargv[i]);
}
+static void add_param_to_argv(char *parsestart)
+{
+ int quote_open = 0, escaped = 0, param_len = 0;
+ char param_buffer[1024], *curchar;
+
+ /* After fighting with strtok enough, here's now
+ * a 'real' parser. According to Rusty I'm now no
+ * longer a real hacker, but I can live with that */
+
+ for (curchar = parsestart; *curchar; curchar++) {
+ if (quote_open) {
+ if (escaped) {
+ param_buffer[param_len++] = *curchar;
+ escaped = 0;
+ continue;
+ } else if (*curchar == '\\') {
+ escaped = 1;
+ continue;
+ } else if (*curchar == '"') {
+ quote_open = 0;
+ *curchar = ' ';
+ } else {
+ param_buffer[param_len++] = *curchar;
+ continue;
+ }
+ } else {
+ if (*curchar == '"') {
+ quote_open = 1;
+ continue;
+ }
+ }
+
+ if (*curchar == ' '
+ || *curchar == '\t'
+ || * curchar == '\n') {
+ if (!param_len) {
+ /* two spaces? */
+ continue;
+ }
+
+ param_buffer[param_len] = '\0';
+
+ /* check if table name specified */
+ if (!strncmp(param_buffer, "-t", 2)
+ || !strncmp(param_buffer, "--table", 8)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Line %u seems to have a "
+ "-t table option.\n", line);
+ exit(1);
+ }
+
+ add_argv(param_buffer);
+ param_len = 0;
+ } else {
+ /* regular character, copy to buffer */
+ param_buffer[param_len++] = *curchar;
+
+ if (param_len >= sizeof(param_buffer))
+ xtables_error(PARAMETER_PROBLEM,
+ "Parameter too long!");
+ }
+ }
+}
+
int
iptables_restore_main(int argc, char *argv[])
{
@@ -325,11 +389,6 @@ iptables_restore_main(int argc, char *argv[])
char *bcnt = NULL;
char *parsestart;
- /* the parser */
- char *curchar;
- int quote_open, escaped;
- size_t param_len;
-
/* reset the newargv */
newargc = 0;
@@ -370,69 +429,7 @@ iptables_restore_main(int argc, char *argv[])
add_argv((char *) bcnt);
}
- /* After fighting with strtok enough, here's now
- * a 'real' parser. According to Rusty I'm now no
- * longer a real hacker, but I can live with that */
-
- quote_open = 0;
- escaped = 0;
- param_len = 0;
-
- for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
- if (quote_open) {
- if (escaped) {
- param_buffer[param_len++] = *curchar;
- escaped = 0;
- continue;
- } else if (*curchar == '\\') {
- escaped = 1;
- continue;
- } else if (*curchar == '"') {
- quote_open = 0;
- *curchar = ' ';
- } else {
- param_buffer[param_len++] = *curchar;
- continue;
- }
- } else {
- if (*curchar == '"') {
- quote_open = 1;
- continue;
- }
- }
-
- if (*curchar == ' '
- || *curchar == '\t'
- || * curchar == '\n') {
- if (!param_len) {
- /* two spaces? */
- continue;
- }
-
- param_buffer[param_len] = '\0';
-
- /* check if table name specified */
- if (!strncmp(param_buffer, "-t", 2)
- || !strncmp(param_buffer, "--table", 8)) {
- xtables_error(PARAMETER_PROBLEM,
- "Line %u seems to have a "
- "-t table option.\n", line);
- exit(1);
- }
-
- add_argv(param_buffer);
- param_len = 0;
- } else {
- /* regular character, copy to buffer */
- param_buffer[param_len++] = *curchar;
-
- if (param_len >= sizeof(param_buffer))
- xtables_error(PARAMETER_PROBLEM,
- "Parameter too long!");
- }
- }
+ add_param_to_argv(parsestart);
DEBUGP("calling do_command4(%u, argv, &%s, handle):\n",
newargc, curtable);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-23 10:38 [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7) pablo
@ 2012-07-23 11:29 ` Eric Dumazet
2012-07-23 11:38 ` Eric Dumazet
2012-07-23 12:19 ` Jan Engelhardt
1 sibling, 1 reply; 11+ messages in thread
From: Eric Dumazet @ 2012-07-23 11:29 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netfilter
On Mon, 2012-07-23 at 12:38 +0200, pablo@netfilter.org wrote:
> From: Pablo Neira Ayuso <pablo@netfilter.org>
>
> This patch seems to be a mere cleanup that moves the parameter parsing
> code to add_param_to_argv.
>
> But, in reality, it also fixes iptables whe compiled with gcc-4.7.
>
> Moving param_buffer declaration out of the loop seems to resolve the
> issue. gcc-4.7 seems to be generating bad code regarding param_buffer.
>
> @@ -380,9 +380,9 @@
> quote_open = 0;
> escaped = 0;
> param_len = 0;
> + char param_buffer[1024];
>
> for (curchar = parsestart; *curchar; curchar++) {
> - char param_buffer[1024];
>
> if (quote_open) {
> if (escaped) {
>
> But I have hard time to apply this patch in such a way. Instead, I came
> up with the idea of this cleanup, which does not harm after all (and fixes
> the issue for us).
>
> Sorry, I didn't have the time to further debug this issue, but it would be
> worth to investigate what's going wrong and ping gcc people.
Bug seems that iptables forgot that "char param_buffer[1024];" can
disappear at the end of the block :
for (curchar = parsestart; *curchar; curchar++) {
char param_buffer[1024];
...
}
// here param_buffer[1024] is lost, so any var pointing
// to it can mess stack
previous gcc were probably not so aggressive.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-23 11:29 ` Eric Dumazet
@ 2012-07-23 11:38 ` Eric Dumazet
2012-07-23 13:08 ` Pablo Neira Ayuso
2012-07-30 1:37 ` Pablo Neira Ayuso
0 siblings, 2 replies; 11+ messages in thread
From: Eric Dumazet @ 2012-07-23 11:38 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netfilter
On Mon, 2012-07-23 at 13:29 +0200, Eric Dumazet wrote:
> On Mon, 2012-07-23 at 12:38 +0200, pablo@netfilter.org wrote:
> > From: Pablo Neira Ayuso <pablo@netfilter.org>
> >
> > This patch seems to be a mere cleanup that moves the parameter parsing
> > code to add_param_to_argv.
> >
> > But, in reality, it also fixes iptables whe compiled with gcc-4.7.
> >
> > Moving param_buffer declaration out of the loop seems to resolve the
> > issue. gcc-4.7 seems to be generating bad code regarding param_buffer.
> >
> > @@ -380,9 +380,9 @@
> > quote_open = 0;
> > escaped = 0;
> > param_len = 0;
> > + char param_buffer[1024];
> >
> > for (curchar = parsestart; *curchar; curchar++) {
> > - char param_buffer[1024];
> >
> > if (quote_open) {
> > if (escaped) {
> >
> > But I have hard time to apply this patch in such a way. Instead, I came
> > up with the idea of this cleanup, which does not harm after all (and fixes
> > the issue for us).
> >
> > Sorry, I didn't have the time to further debug this issue, but it would be
> > worth to investigate what's going wrong and ping gcc people.
>
> Bug seems that iptables forgot that "char param_buffer[1024];" can
> disappear at the end of the block :
>
> for (curchar = parsestart; *curchar; curchar++) {
> char param_buffer[1024];
> ...
> }
>
> // here param_buffer[1024] is lost, so any var pointing
> // to it can mess stack
>
> previous gcc were probably not so aggressive.
>
>
Oh well, add_argv() does a strdup(), so iptables code seems fine.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-23 10:38 [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7) pablo
2012-07-23 11:29 ` Eric Dumazet
@ 2012-07-23 12:19 ` Jan Engelhardt
2012-07-23 13:04 ` Pablo Neira Ayuso
1 sibling, 1 reply; 11+ messages in thread
From: Jan Engelhardt @ 2012-07-23 12:19 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, netfilter
On Monday 2012-07-23 12:38, pablo@netfilter.org wrote:
>From: Pablo Neira Ayuso <pablo@netfilter.org>
>
>This patch seems to be a mere cleanup that moves the parameter parsing
>code to add_param_to_argv.
>
>But, in reality, it also fixes iptables whe compiled with gcc-4.7.
How does the problem manifest?
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-23 12:19 ` Jan Engelhardt
@ 2012-07-23 13:04 ` Pablo Neira Ayuso
0 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2012-07-23 13:04 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: netfilter-devel, netfilter
On Mon, Jul 23, 2012 at 02:19:11PM +0200, Jan Engelhardt wrote:
> On Monday 2012-07-23 12:38, pablo@netfilter.org wrote:
>
> >From: Pablo Neira Ayuso <pablo@netfilter.org>
> >
> >This patch seems to be a mere cleanup that moves the parameter parsing
> >code to add_param_to_argv.
> >
> >But, in reality, it also fixes iptables whe compiled with gcc-4.7.
>
> How does the problem manifest?
You can check:
http://bugzilla.netfilter.org/show_bug.cgi?id=774
It tastes like a memory corruption.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-23 11:38 ` Eric Dumazet
@ 2012-07-23 13:08 ` Pablo Neira Ayuso
2012-07-30 1:37 ` Pablo Neira Ayuso
1 sibling, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2012-07-23 13:08 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netfilter-devel, netfilter
On Mon, Jul 23, 2012 at 01:38:48PM +0200, Eric Dumazet wrote:
> On Mon, 2012-07-23 at 13:29 +0200, Eric Dumazet wrote:
> > On Mon, 2012-07-23 at 12:38 +0200, pablo@netfilter.org wrote:
> > > From: Pablo Neira Ayuso <pablo@netfilter.org>
> > >
> > > This patch seems to be a mere cleanup that moves the parameter parsing
> > > code to add_param_to_argv.
> > >
> > > But, in reality, it also fixes iptables whe compiled with gcc-4.7.
> > >
> > > Moving param_buffer declaration out of the loop seems to resolve the
> > > issue. gcc-4.7 seems to be generating bad code regarding param_buffer.
> > >
> > > @@ -380,9 +380,9 @@
> > > quote_open = 0;
> > > escaped = 0;
> > > param_len = 0;
> > > + char param_buffer[1024];
> > >
> > > for (curchar = parsestart; *curchar; curchar++) {
> > > - char param_buffer[1024];
> > >
> > > if (quote_open) {
> > > if (escaped) {
> > >
> > > But I have hard time to apply this patch in such a way. Instead, I came
> > > up with the idea of this cleanup, which does not harm after all (and fixes
> > > the issue for us).
> > >
> > > Sorry, I didn't have the time to further debug this issue, but it would be
> > > worth to investigate what's going wrong and ping gcc people.
> >
> > Bug seems that iptables forgot that "char param_buffer[1024];" can
> > disappear at the end of the block :
> >
> > for (curchar = parsestart; *curchar; curchar++) {
> > char param_buffer[1024];
> > ...
> > }
> >
> > // here param_buffer[1024] is lost, so any var pointing
> > // to it can mess stack
> >
> > previous gcc were probably not so aggressive.
>
> Oh well, add_argv() does a strdup(), so iptables code seems fine.
I think so, I don't find any possible dereference to param_buffer out
of that loop and it does strdup accordingly.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-23 11:38 ` Eric Dumazet
@ 2012-07-30 1:37 ` Pablo Neira Ayuso
2012-07-30 1:37 ` Pablo Neira Ayuso
1 sibling, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2012-07-30 1:37 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netfilter-devel, netfilter
[-- Attachment #1: Type: text/plain, Size: 2192 bytes --]
On Mon, Jul 23, 2012 at 01:38:48PM +0200, Eric Dumazet wrote:
> On Mon, 2012-07-23 at 13:29 +0200, Eric Dumazet wrote:
> > On Mon, 2012-07-23 at 12:38 +0200, pablo@netfilter.org wrote:
> > > From: Pablo Neira Ayuso <pablo@netfilter.org>
> > >
> > > This patch seems to be a mere cleanup that moves the parameter parsing
> > > code to add_param_to_argv.
> > >
> > > But, in reality, it also fixes iptables whe compiled with gcc-4.7.
> > >
> > > Moving param_buffer declaration out of the loop seems to resolve the
> > > issue. gcc-4.7 seems to be generating bad code regarding param_buffer.
> > >
> > > @@ -380,9 +380,9 @@
> > > quote_open = 0;
> > > escaped = 0;
> > > param_len = 0;
> > > + char param_buffer[1024];
> > >
> > > for (curchar = parsestart; *curchar; curchar++) {
> > > - char param_buffer[1024];
> > >
> > > if (quote_open) {
> > > if (escaped) {
> > >
> > > But I have hard time to apply this patch in such a way. Instead, I came
> > > up with the idea of this cleanup, which does not harm after all (and fixes
> > > the issue for us).
> > >
> > > Sorry, I didn't have the time to further debug this issue, but it would be
> > > worth to investigate what's going wrong and ping gcc people.
> >
> > Bug seems that iptables forgot that "char param_buffer[1024];" can
> > disappear at the end of the block :
> >
> > for (curchar = parsestart; *curchar; curchar++) {
> > char param_buffer[1024];
> > ...
> > }
> >
> > // here param_buffer[1024] is lost, so any var pointing
> > // to it can mess stack
> >
> > previous gcc were probably not so aggressive.
>
> Oh well, add_argv() does a strdup(), so iptables code seems fine.
I thought the same, but one contributor has put some on light on this.
I'm going to revert the patch that I applied to fix this and apply
the one that comes with this email instead.
It contains a simple description of the problem, I think it's good for
the record (distro maintainers will likely google for this).
[-- Attachment #2: 0001-iptables-restore-fix-memory-corruption-in-parameter-.patch --]
[-- Type: text/x-diff, Size: 2836 bytes --]
>From 8cfcb0137f4aee880ec749cd2356148325f6085d Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Mon, 30 Jul 2012 03:08:51 +0200
Subject: [PATCH] iptables-restore: fix memory corruption in parameter parsing
with gcc-4.7
This patch fixes a memory corruption that has been in iptables-restore since
time ago. The problem has shown up with gcc-4.7. This version of gcc seem to
perform more agressive memory management than previous.
Peter Lekensteyn provided the following sample code similar to the one
in iptables-restore:
int i = 0;
for (;;) {
char x[5];
x[i] = '0' + i;
if (++i == 4) {
x[i] = '\0'; /* terminate string with null byte */
printf("%s\n", x);
break;
}
}
Many may expect 0123 as output. But GCC 4.7 does not do that when compiling
with optimization enabled (-O1 and higher). It instead puts random data in the
first bytes of the character array, which becomes:
| 0 | 1 | 2 | 3 | 4 |
| RANDOM | '3' | '\0' |
Since the array is declared inside the scope of loop's body, you can think of
it as of a new array being allocated in the automatic storage area for each
loop iteration.
The correct code should be:
char x[5];
for (;;) {
x[i] = '0' + i;
if (++i == 4) {
x[i] = '\0'; /* terminate string with null byte */
printf("%s\n", x);
break;
}
}
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
iptables/ip6tables-restore.c | 3 +--
iptables/iptables-restore.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c
index 3894d68..1ec3dd9 100644
--- a/iptables/ip6tables-restore.c
+++ b/iptables/ip6tables-restore.c
@@ -329,6 +329,7 @@ int ip6tables_restore_main(int argc, char *argv[])
char *curchar;
int quote_open, escaped;
size_t param_len;
+ char param_buffer[1024];
/* reset the newargv */
newargc = 0;
@@ -379,8 +380,6 @@ int ip6tables_restore_main(int argc, char *argv[])
param_len = 0;
for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
if (quote_open) {
if (escaped) {
param_buffer[param_len++] = *curchar;
diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c
index 034f960..9f51f99 100644
--- a/iptables/iptables-restore.c
+++ b/iptables/iptables-restore.c
@@ -329,6 +329,7 @@ iptables_restore_main(int argc, char *argv[])
char *curchar;
int quote_open, escaped;
size_t param_len;
+ char param_buffer[1024];
/* reset the newargv */
newargc = 0;
@@ -379,8 +380,6 @@ iptables_restore_main(int argc, char *argv[])
param_len = 0;
for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
if (quote_open) {
if (escaped) {
param_buffer[param_len++] = *curchar;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
@ 2012-07-30 1:37 ` Pablo Neira Ayuso
0 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2012-07-30 1:37 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netfilter-devel, netfilter
[-- Attachment #1: Type: text/plain, Size: 2192 bytes --]
On Mon, Jul 23, 2012 at 01:38:48PM +0200, Eric Dumazet wrote:
> On Mon, 2012-07-23 at 13:29 +0200, Eric Dumazet wrote:
> > On Mon, 2012-07-23 at 12:38 +0200, pablo@netfilter.org wrote:
> > > From: Pablo Neira Ayuso <pablo@netfilter.org>
> > >
> > > This patch seems to be a mere cleanup that moves the parameter parsing
> > > code to add_param_to_argv.
> > >
> > > But, in reality, it also fixes iptables whe compiled with gcc-4.7.
> > >
> > > Moving param_buffer declaration out of the loop seems to resolve the
> > > issue. gcc-4.7 seems to be generating bad code regarding param_buffer.
> > >
> > > @@ -380,9 +380,9 @@
> > > quote_open = 0;
> > > escaped = 0;
> > > param_len = 0;
> > > + char param_buffer[1024];
> > >
> > > for (curchar = parsestart; *curchar; curchar++) {
> > > - char param_buffer[1024];
> > >
> > > if (quote_open) {
> > > if (escaped) {
> > >
> > > But I have hard time to apply this patch in such a way. Instead, I came
> > > up with the idea of this cleanup, which does not harm after all (and fixes
> > > the issue for us).
> > >
> > > Sorry, I didn't have the time to further debug this issue, but it would be
> > > worth to investigate what's going wrong and ping gcc people.
> >
> > Bug seems that iptables forgot that "char param_buffer[1024];" can
> > disappear at the end of the block :
> >
> > for (curchar = parsestart; *curchar; curchar++) {
> > char param_buffer[1024];
> > ...
> > }
> >
> > // here param_buffer[1024] is lost, so any var pointing
> > // to it can mess stack
> >
> > previous gcc were probably not so aggressive.
>
> Oh well, add_argv() does a strdup(), so iptables code seems fine.
I thought the same, but one contributor has put some on light on this.
I'm going to revert the patch that I applied to fix this and apply
the one that comes with this email instead.
It contains a simple description of the problem, I think it's good for
the record (distro maintainers will likely google for this).
[-- Attachment #2: 0001-iptables-restore-fix-memory-corruption-in-parameter-.patch --]
[-- Type: text/x-diff, Size: 2835 bytes --]
From 8cfcb0137f4aee880ec749cd2356148325f6085d Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Mon, 30 Jul 2012 03:08:51 +0200
Subject: [PATCH] iptables-restore: fix memory corruption in parameter parsing
with gcc-4.7
This patch fixes a memory corruption that has been in iptables-restore since
time ago. The problem has shown up with gcc-4.7. This version of gcc seem to
perform more agressive memory management than previous.
Peter Lekensteyn provided the following sample code similar to the one
in iptables-restore:
int i = 0;
for (;;) {
char x[5];
x[i] = '0' + i;
if (++i == 4) {
x[i] = '\0'; /* terminate string with null byte */
printf("%s\n", x);
break;
}
}
Many may expect 0123 as output. But GCC 4.7 does not do that when compiling
with optimization enabled (-O1 and higher). It instead puts random data in the
first bytes of the character array, which becomes:
| 0 | 1 | 2 | 3 | 4 |
| RANDOM | '3' | '\0' |
Since the array is declared inside the scope of loop's body, you can think of
it as of a new array being allocated in the automatic storage area for each
loop iteration.
The correct code should be:
char x[5];
for (;;) {
x[i] = '0' + i;
if (++i == 4) {
x[i] = '\0'; /* terminate string with null byte */
printf("%s\n", x);
break;
}
}
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
iptables/ip6tables-restore.c | 3 +--
iptables/iptables-restore.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/iptables/ip6tables-restore.c b/iptables/ip6tables-restore.c
index 3894d68..1ec3dd9 100644
--- a/iptables/ip6tables-restore.c
+++ b/iptables/ip6tables-restore.c
@@ -329,6 +329,7 @@ int ip6tables_restore_main(int argc, char *argv[])
char *curchar;
int quote_open, escaped;
size_t param_len;
+ char param_buffer[1024];
/* reset the newargv */
newargc = 0;
@@ -379,8 +380,6 @@ int ip6tables_restore_main(int argc, char *argv[])
param_len = 0;
for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
if (quote_open) {
if (escaped) {
param_buffer[param_len++] = *curchar;
diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c
index 034f960..9f51f99 100644
--- a/iptables/iptables-restore.c
+++ b/iptables/iptables-restore.c
@@ -329,6 +329,7 @@ iptables_restore_main(int argc, char *argv[])
char *curchar;
int quote_open, escaped;
size_t param_len;
+ char param_buffer[1024];
/* reset the newargv */
newargc = 0;
@@ -379,8 +380,6 @@ iptables_restore_main(int argc, char *argv[])
param_len = 0;
for (curchar = parsestart; *curchar; curchar++) {
- char param_buffer[1024];
-
if (quote_open) {
if (escaped) {
param_buffer[param_len++] = *curchar;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-30 1:37 ` Pablo Neira Ayuso
(?)
@ 2012-07-30 1:40 ` Pablo Neira Ayuso
-1 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2012-07-30 1:40 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netfilter-devel, netfilter
On Mon, Jul 30, 2012 at 03:37:07AM +0200, Pablo Neira Ayuso wrote:
> From 8cfcb0137f4aee880ec749cd2356148325f6085d Mon Sep 17 00:00:00 2001
> From: Pablo Neira Ayuso <pablo@netfilter.org>
> Date: Mon, 30 Jul 2012 03:08:51 +0200
> Subject: [PATCH] iptables-restore: fix memory corruption in parameter parsing
> with gcc-4.7
I'm going to change the title of this patch, memory corruption does
not seem appropriate. Instead, the problem seems to be related to
wrong assumptions on uninitialized memory area.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-07-30 1:37 ` Pablo Neira Ayuso
(?)
(?)
@ 2012-08-02 19:37 ` Jan Engelhardt
2012-08-03 9:15 ` Pablo Neira Ayuso
-1 siblings, 1 reply; 11+ messages in thread
From: Jan Engelhardt @ 2012-08-02 19:37 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Eric Dumazet, netfilter-devel, netfilter
On Monday 2012-07-30 03:37, Pablo Neira Ayuso wrote:
>> > // here param_buffer[1024] is lost, so any var pointing
>> > // to it can mess stack
>> >
>> > previous gcc were probably not so aggressive.
>>
>> Oh well, add_argv() does a strdup(), so iptables code seems fine.
>
>I thought the same, but one contributor has put some on light on this.
>
>I'm going to revert the patch that I applied to fix this and apply
>the one that comes with this email instead.
>
>It contains a simple description of the problem, I think it's good for
>the record (distro maintainers will likely google for this).
Your code cleanup, by moving the code into a separate function,
is however still desired :)
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
2012-08-02 19:37 ` Jan Engelhardt
@ 2012-08-03 9:15 ` Pablo Neira Ayuso
0 siblings, 0 replies; 11+ messages in thread
From: Pablo Neira Ayuso @ 2012-08-03 9:15 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Eric Dumazet, netfilter-devel, netfilter
On Thu, Aug 02, 2012 at 09:37:10PM +0200, Jan Engelhardt wrote:
>
> On Monday 2012-07-30 03:37, Pablo Neira Ayuso wrote:
> >> > // here param_buffer[1024] is lost, so any var pointing
> >> > // to it can mess stack
> >> >
> >> > previous gcc were probably not so aggressive.
> >>
> >> Oh well, add_argv() does a strdup(), so iptables code seems fine.
> >
> >I thought the same, but one contributor has put some on light on this.
> >
> >I'm going to revert the patch that I applied to fix this and apply
> >the one that comes with this email instead.
> >
> >It contains a simple description of the problem, I think it's good for
> >the record (distro maintainers will likely google for this).
>
> Your code cleanup, by moving the code into a separate function,
> is however still desired :)
OK, it's back:
http://git.netfilter.org/cgi-bin/gitweb.cgi?p=iptables.git;a=commit;h=23a98b56935c42ef460020e37a9ff8006eee58e2
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-08-03 9:15 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-23 10:38 [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7) pablo
2012-07-23 11:29 ` Eric Dumazet
2012-07-23 11:38 ` Eric Dumazet
2012-07-23 13:08 ` Pablo Neira Ayuso
2012-07-30 1:37 ` Pablo Neira Ayuso
2012-07-30 1:37 ` Pablo Neira Ayuso
2012-07-30 1:40 ` Pablo Neira Ayuso
2012-08-02 19:37 ` Jan Engelhardt
2012-08-03 9:15 ` Pablo Neira Ayuso
2012-07-23 12:19 ` Jan Engelhardt
2012-07-23 13:04 ` Pablo Neira Ayuso
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.