netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist
@ 2014-05-08 11:48 Andreas Greve
  2014-05-09 20:34 ` Stephen Hemminger
  2014-05-10  9:11 ` Andreas Greve
  0 siblings, 2 replies; 5+ messages in thread
From: Andreas Greve @ 2014-05-08 11:48 UTC (permalink / raw)
  To: stephen; +Cc: andreas.greve, netdev

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

Dear Stephen Hemminger, Dear List Members,

the command

tc filter show dev eth1 parent ffff:

raise a segmentation fault if there are more than one filter rule with 
action -j MARK exists.

Reason:
In print_ipt(...) xtables will be initialzed with a pointer to the 
static struct tcipt_globals at xtables_init_all(). Later on the fields 
.opts and .options_offset of tcipt_globals are modified.  The call of 
xtables_free_opts(1) at the end of print_ipt(...) does not restore the 
original values of tcipt_globals for the modified fields. It only frees 
some allocated memory and sets .opts to NULL. This leads to a 
segmentation fault when print_ipt()
is called for the next filter rule with action -j MARK.

Fix: (patch attached)
Cloneing tcipt_globals on the stack as tmp_tcipt_globals and use it 
instead of tcipt_globals, so tcipt_globals will be not modified.

Tests:
I only have done limit tests for this fix ( action -j MARK ) on a debian 
wheezy iproute2 package build from source based on upstream/3.14.0. The 
system is a little bit special  kernel 3.12.17-xen on xen-4.4.1-pre.


Andreas Henriksson (debian iproute maintainer) give me an other idea of 
how to fix this bug by modifying  xtables_free_opts() so that it sets 
.opts = .orig_opts instead .opts = NULL. This should  avoid having to 
duplicate the entire struct each time.

I prefer the cloning  because:

1)  In my understanding the variable tcipt_globals is a complex 
"constant" that should never be modified. ( Is that right ?)

2) If we want to do the fix in xtables_free_opts we have to change the 
struct xtables_globals because we need for all fields .orig fields I 
think this will  make all things much more complicated.


additional Brainstorms:

a ) Perhaps we have to think about of a deep clone of tcipt_globals to 
protect the underlaying option array
b ) makes cloning of  tcipt_globals sense in  parse_ipt(...)
But for this two decisions my understanding of the whole system is not 
enough.


I hope the Information helps

Thanks

Best wishes


Andreas Greve








Andreas Henriksson


Stephen Hemminger


[-- Attachment #2: 0001-print_ipt-segfault-if-more-then-one-filter-with-acti.patch --]
[-- Type: text/x-patch, Size: 2852 bytes --]

>From 2be366b5b534af61756e1eb69e26fcf9c4544aa7 Mon Sep 17 00:00:00 2001
From: Andreas Greve <andreas.greve@a-greve.de>
Date: Thu, 8 May 2014 12:03:16 +0200
Subject: [PATCH] print_ipt: segfault if more then one filter with action -j
 MARK.

tc fulter show ... produce a segmentation fault if more than one
filter rule with action -j MARK exists.

Reason: In print_ipt(...) xtables will be initialzed with a
pointer to the static struct tcipt_globals at xtables_init_all().
Later on the fields .opts and .options_offset of tcipt_globals are
modified. The call of xtables_free_opts(1) at the end of print(...)
does not restore the original values of tcipt_globals for the
modified fields. It only frees some allocated memory and sets
.opts to NULL. This leads to a segmentation fault when print_ipt()
is called for the next filter rule with action -j MARK.

Fix: Cloneing tcipt_globals on the stack as tmp_tcipt_globals and
use it instead of tcipt_globals, so tcipt_globals will be not
modified.

Signed-off-by: Andreas Greve <andreas.greve@a-greve.de>
---
 tc/m_xt.c |   18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/tc/m_xt.c b/tc/m_xt.c
index 27029c1..873adad 100644
--- a/tc/m_xt.c
+++ b/tc/m_xt.c
@@ -298,7 +298,15 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
 	if (arg == NULL)
 		return -1;
 
-	xtables_init_all(&tcipt_globals, NFPROTO_IPV4);
+	/* 
+	   clone tcipt_globals because .opts and .options_offset  will be modified later and not 
+           restored by iptables. If tcipt_globals is not cloned the modification tcipt_globals will 
+           cause a segmentation fault if more than one filter rule  with action -j  exists.
+        */
+	struct xtables_globals tmp_tcipt_globals;
+	memcpy (&tmp_tcipt_globals, &tcipt_globals, sizeof(struct xtables_globals) );
+
+	xtables_init_all(&tmp_tcipt_globals, NFPROTO_IPV4);
 	set_lib_dir();
 
 	parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
@@ -333,12 +341,12 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
 			}
 
 #if (XTABLES_VERSION_CODE >= 6)
-		opts = xtables_options_xfrm(tcipt_globals.orig_opts,
-					    tcipt_globals.opts,
+		opts = xtables_options_xfrm(tmp_tcipt_globals.orig_opts,
+					    tmp_tcipt_globals.opts,
 					    m->x6_options,
 					    &m->option_offset);
 #else
-		opts = xtables_merge_options(tcipt_globals.opts,
+		opts = xtables_merge_options(tmp_tcipt_globals.opts,
 					     m->extra_opts,
 					     &m->option_offset);
 #endif
@@ -346,7 +354,7 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
 		fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg);
 		return -1;
 	} else
-		tcipt_globals.opts = opts;
+		tmp_tcipt_globals.opts = opts;
 		} else {
 			fprintf(stderr, " failed to find target %s\n\n",
 				t->u.user.name);
-- 
1.7.10.4


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

* Re: Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist
  2014-05-08 11:48 Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist Andreas Greve
@ 2014-05-09 20:34 ` Stephen Hemminger
  2014-05-10  9:11 ` Andreas Greve
  1 sibling, 0 replies; 5+ messages in thread
From: Stephen Hemminger @ 2014-05-09 20:34 UTC (permalink / raw)
  To: andreas.greve; +Cc: netdev

On Thu, 08 May 2014 13:48:19 +0200
Andreas Greve <andreas.greve@a-greve.de> wrote:

> +	/* 
> +	   clone tcipt_globals because .opts and .options_offset  will be modified later and not 
> +           restored by iptables. If tcipt_globals is not cloned the modification tcipt_globals will 
> +           cause a segmentation fault if more than one filter rule  with action -j  exists.
> +        */
> +	struct xtables_globals tmp_tcipt_globals;
> +	memcpy (&tmp_tcipt_globals, &tcipt_globals, sizeof(struct xtables_globals) );
> +

Please use structure assignment instead of memcpy().
Structure assignment makes sure that types match. mempcpy does not.

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

* Re: Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist
  2014-05-08 11:48 Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist Andreas Greve
  2014-05-09 20:34 ` Stephen Hemminger
@ 2014-05-10  9:11 ` Andreas Greve
  2014-05-10  9:19   ` Andreas Greve
  1 sibling, 1 reply; 5+ messages in thread
From: Andreas Greve @ 2014-05-10  9:11 UTC (permalink / raw)
  To: stephen; +Cc: netdev

Dear Stephen Hemminger, Dear List Members,

this is a corrected/optimized version of the patch
Thanks to Stephen Hemminger, for giving me the hint to use structure 
assignment instead of
memcpy().

Best wishes

Andreas Greve

On 05/08/14 13:48, Andreas Greve wrote:
> Dear Stephen Hemminger, Dear List Members,
>
> the command
>
> tc filter show dev eth1 parent ffff:
>
> raise a segmentation fault if there are more than one filter rule with 
> action -j MARK exists.
>
> Reason:
> In print_ipt(...) xtables will be initialzed with a pointer to the 
> static struct tcipt_globals at xtables_init_all(). Later on the fields 
> .opts and .options_offset of tcipt_globals are modified. The call of 
> xtables_free_opts(1) at the end of print_ipt(...) does not restore the 
> original values of tcipt_globals for the modified fields. It only 
> frees some allocated memory and sets .opts to NULL. This leads to a 
> segmentation fault when print_ipt()
> is called for the next filter rule with action -j MARK.
>
> Fix: (patch attached)
> Cloneing tcipt_globals on the stack as tmp_tcipt_globals and use it 
> instead of tcipt_globals, so tcipt_globals will be not modified.
>
> Tests:
> I only have done limit tests for this fix ( action -j MARK ) on a 
> debian wheezy iproute2 package build from source based on 
> upstream/3.14.0. The system is a little bit special  kernel 
> 3.12.17-xen on xen-4.4.1-pre.
>
>
> Andreas Henriksson (debian iproute maintainer) give me an other idea 
> of how to fix this bug by modifying  xtables_free_opts() so that it 
> sets .opts = .orig_opts instead .opts = NULL. This should avoid having 
> to duplicate the entire struct each time.
>
> I prefer the cloning  because:
>
> 1)  In my understanding the variable tcipt_globals is a complex 
> "constant" that should never be modified. ( Is that right ?)
>
> 2) If we want to do the fix in xtables_free_opts we have to change the 
> struct xtables_globals because we need for all fields .orig fields I 
> think this will  make all things much more complicated.
>
>
> additional Brainstorms:
>
> a ) Perhaps we have to think about of a deep clone of tcipt_globals to 
> protect the underlaying option array
> b ) makes cloning of  tcipt_globals sense in  parse_ipt(...)
> But for this two decisions my understanding of the whole system is not 
> enough.
>
>
> I hope the Information helps
>
> Thanks
>
> Best wishes
>
>
> Andreas Greve
>
>
>
>
>
>
>
>
> Andreas Henriksson
>
>
> Stephen Hemminger
>

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

* Re: Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist
  2014-05-10  9:11 ` Andreas Greve
@ 2014-05-10  9:19   ` Andreas Greve
  2014-05-13 20:10     ` Stephen Hemminger
  0 siblings, 1 reply; 5+ messages in thread
From: Andreas Greve @ 2014-05-10  9:19 UTC (permalink / raw)
  To: stephen; +Cc: netdev, andreas.greve

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

sorry its to early for me ;)

here the missing attachment.

On 05/10/14 11:11, Andreas Greve wrote:
> Dear Stephen Hemminger, Dear List Members,
>
> this is a corrected/optimized version of the patch
> Thanks to Stephen Hemminger, for giving me the hint to use structure 
> assignment instead of
> memcpy().
>
> Best wishes
>
> Andreas Greve
>
> On 05/08/14 13:48, Andreas Greve wrote:
>> Dear Stephen Hemminger, Dear List Members,
>>
>> the command
>>
>> tc filter show dev eth1 parent ffff:
>>
>> raise a segmentation fault if there are more than one filter rule 
>> with action -j MARK exists.
>>
>> Reason:
>> In print_ipt(...) xtables will be initialzed with a pointer to the 
>> static struct tcipt_globals at xtables_init_all(). Later on the 
>> fields .opts and .options_offset of tcipt_globals are modified. The 
>> call of xtables_free_opts(1) at the end of print_ipt(...) does not 
>> restore the original values of tcipt_globals for the modified fields. 
>> It only frees some allocated memory and sets .opts to NULL. This 
>> leads to a segmentation fault when print_ipt()
>> is called for the next filter rule with action -j MARK.
>>
>> Fix: (patch attached)
>> Cloneing tcipt_globals on the stack as tmp_tcipt_globals and use it 
>> instead of tcipt_globals, so tcipt_globals will be not modified.
>>
>> Tests:
>> I only have done limit tests for this fix ( action -j MARK ) on a 
>> debian wheezy iproute2 package build from source based on 
>> upstream/3.14.0. The system is a little bit special  kernel 
>> 3.12.17-xen on xen-4.4.1-pre.
>>
>>
>> Andreas Henriksson (debian iproute maintainer) give me an other idea 
>> of how to fix this bug by modifying  xtables_free_opts() so that it 
>> sets .opts = .orig_opts instead .opts = NULL. This should avoid 
>> having to duplicate the entire struct each time.
>>
>> I prefer the cloning  because:
>>
>> 1)  In my understanding the variable tcipt_globals is a complex 
>> "constant" that should never be modified. ( Is that right ?)
>>
>> 2) If we want to do the fix in xtables_free_opts we have to change 
>> the struct xtables_globals because we need for all fields .orig 
>> fields I think this will  make all things much more complicated.
>>
>>
>> additional Brainstorms:
>>
>> a ) Perhaps we have to think about of a deep clone of tcipt_globals 
>> to protect the underlaying option array
>> b ) makes cloning of  tcipt_globals sense in  parse_ipt(...)
>> But for this two decisions my understanding of the whole system is 
>> not enough.
>>
>>
>> I hope the Information helps
>>
>> Thanks
>>
>> Best wishes
>>
>>
>> Andreas Greve
>>
>>
>>
>>
>>
>>
>>
>>
>> Andreas Henriksson
>>
>>
>> Stephen Hemminger
>>
>


[-- Attachment #2: 0001-print_ipt-segfault-if-more-then-one-filter-with-acti.patch --]
[-- Type: text/x-patch, Size: 2793 bytes --]

>From fdf33181ade1320a6de79ac57d0f751b571f1dd8 Mon Sep 17 00:00:00 2001
From: Andreas Greve <andreas.greve@a-greve.de>
Date: Sat, 10 May 2014 10:47:01 +0200
Subject: [PATCH] print_ipt: segfault if more then one filter with action -j
 MARK.

BUG: tc filter show ... produce a segmentation fault if more than one
filter rule with action -j MARK exists.

Reason: In print_ipt(...) xtables will be initialzed with a
pointer to the static struct tcipt_globals at xtables_init_all().
Later on the fields .opts and .options_offset of tcipt_globals are
modified. The call of xtables_free_opts(1) at the end of print(...)
does not restore the original values of tcipt_globals for the
modified fields. It only frees some allocated memory and sets
.opts to NULL. This leads to a segmentation fault when print_ipt()
is called for the next filter rule with action -j MARK.

Fix: Cloneing tcipt_globals on the stack as tmp_tcipt_globals and
use it instead of tcipt_globals, so tcipt_globals will be not
modified.

Signed-off-by: Andreas Greve <andreas.greve@a-greve.de>
---
 tc/m_xt.c |   17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/tc/m_xt.c b/tc/m_xt.c
index 27029c1..274df1d 100644
--- a/tc/m_xt.c
+++ b/tc/m_xt.c
@@ -298,7 +298,14 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
 	if (arg == NULL)
 		return -1;
 
-	xtables_init_all(&tcipt_globals, NFPROTO_IPV4);
+	/* 
+	   clone tcipt_globals because .opts and .options_offset  will be modified later and not 
+           restored by iptables. If tcipt_globals is not cloned the modification tcipt_globals will 
+           cause a segmentation fault if more than one filter rule  with action -j  exists.
+        */
+	struct xtables_globals tmp_tcipt_globals = tcipt_globals;
+
+	xtables_init_all(&tmp_tcipt_globals, NFPROTO_IPV4);
 	set_lib_dir();
 
 	parse_rtattr_nested(tb, TCA_IPT_MAX, arg);
@@ -333,12 +340,12 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
 			}
 
 #if (XTABLES_VERSION_CODE >= 6)
-		opts = xtables_options_xfrm(tcipt_globals.orig_opts,
-					    tcipt_globals.opts,
+		opts = xtables_options_xfrm(tmp_tcipt_globals.orig_opts,
+					    tmp_tcipt_globals.opts,
 					    m->x6_options,
 					    &m->option_offset);
 #else
-		opts = xtables_merge_options(tcipt_globals.opts,
+		opts = xtables_merge_options(tmp_tcipt_globals.opts,
 					     m->extra_opts,
 					     &m->option_offset);
 #endif
@@ -346,7 +353,7 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
 		fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg);
 		return -1;
 	} else
-		tcipt_globals.opts = opts;
+		tmp_tcipt_globals.opts = opts;
 		} else {
 			fprintf(stderr, " failed to find target %s\n\n",
 				t->u.user.name);
-- 
1.7.10.4


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

* Re: Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist
  2014-05-10  9:19   ` Andreas Greve
@ 2014-05-13 20:10     ` Stephen Hemminger
  0 siblings, 0 replies; 5+ messages in thread
From: Stephen Hemminger @ 2014-05-13 20:10 UTC (permalink / raw)
  To: andreas.greve; +Cc: netdev

On Sat, 10 May 2014 11:19:18 +0200
Andreas Greve <andreas.greve@a-greve.de> wrote:

> sorry its to early for me ;)
> 
> here the missing attachment.
> 
> On 05/10/14 11:11, Andreas Greve wrote:
> > Dear Stephen Hemminger, Dear List Members,
> >
> > this is a corrected/optimized version of the patch
> > Thanks to Stephen Hemminger, for giving me the hint to use structure 
> > assignment instead of
> > memcpy().
> >
> > Best wishes
> >
> > Andreas Greve
> >
> > On 05/08/14 13:48, Andreas Greve wrote:
> >> Dear Stephen Hemminger, Dear List Members,
> >>
> >> the command
> >>
> >> tc filter show dev eth1 parent ffff:
> >>
> >> raise a segmentation fault if there are more than one filter rule 
> >> with action -j MARK exists.
> >>
> >> Reason:
> >> In print_ipt(...) xtables will be initialzed with a pointer to the 
> >> static struct tcipt_globals at xtables_init_all(). Later on the 
> >> fields .opts and .options_offset of tcipt_globals are modified. The 
> >> call of xtables_free_opts(1) at the end of print_ipt(...) does not 
> >> restore the original values of tcipt_globals for the modified fields. 
> >> It only frees some allocated memory and sets .opts to NULL. This 
> >> leads to a segmentation fault when print_ipt()
> >> is called for the next filter rule with action -j MARK.
> >>
> >> Fix: (patch attached)
> >> Cloneing tcipt_globals on the stack as tmp_tcipt_globals and use it 
> >> instead of tcipt_globals, so tcipt_globals will be not modified.
> >>
> >> Tests:
> >> I only have done limit tests for this fix ( action -j MARK ) on a 
> >> debian wheezy iproute2 package build from source based on 
> >> upstream/3.14.0. The system is a little bit special  kernel 
> >> 3.12.17-xen on xen-4.4.1-pre.
> >>
> >>
> >> Andreas Henriksson (debian iproute maintainer) give me an other idea 
> >> of how to fix this bug by modifying  xtables_free_opts() so that it 
> >> sets .opts = .orig_opts instead .opts = NULL. This should avoid 
> >> having to duplicate the entire struct each time.
> >>
> >> I prefer the cloning  because:
> >>
> >> 1)  In my understanding the variable tcipt_globals is a complex 
> >> "constant" that should never be modified. ( Is that right ?)
> >>
> >> 2) If we want to do the fix in xtables_free_opts we have to change 
> >> the struct xtables_globals because we need for all fields .orig 
> >> fields I think this will  make all things much more complicated.
> >>
> >>
> >> additional Brainstorms:
> >>
> >> a ) Perhaps we have to think about of a deep clone of tcipt_globals 
> >> to protect the underlaying option array
> >> b ) makes cloning of  tcipt_globals sense in  parse_ipt(...)
> >> But for this two decisions my understanding of the whole system is 
> >> not enough.
> >>
> >>
> >> I hope the Information helps

Applied, but overly wordy comment simplified, and whitespace issues fixed.

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

end of thread, other threads:[~2014-05-13 20:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-08 11:48 Bug: tc filter show .... raise segfault if more than one rule with action -j MARK exist Andreas Greve
2014-05-09 20:34 ` Stephen Hemminger
2014-05-10  9:11 ` Andreas Greve
2014-05-10  9:19   ` Andreas Greve
2014-05-13 20:10     ` Stephen Hemminger

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).