From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Eric Dumazet <eric.dumazet@gmail.com>
Cc: netfilter-devel@vger.kernel.org, netfilter@vger.kernel.org
Subject: Re: [PATCH] iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)
Date: Mon, 30 Jul 2012 03:37:07 +0200 [thread overview]
Message-ID: <20120730013707.GA2350@1984> (raw)
In-Reply-To: <1343043528.2626.10755.camel@edumazet-glaptop>
[-- 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
next prev parent reply other threads:[~2012-07-30 1:37 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120730013707.GA2350@1984 \
--to=pablo@netfilter.org \
--cc=eric.dumazet@gmail.com \
--cc=netfilter-devel@vger.kernel.org \
--cc=netfilter@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).