]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
fix print_ipt: segfault if more then one filter with action -j MARK.
authorAndreas Greve <andreas.greve@a-greve.de>
Sat, 10 May 2014 09:19:18 +0000 (11:19 +0200)
committerStephen Hemminger <stephen@networkplumber.org>
Tue, 13 May 2014 20:10:31 +0000 (13:10 -0700)
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

index 27029c1b56815f69f3b852ac64434428fb8d9f90..3b0cf95b4906b3829b960d07436042668184cd34 100644 (file)
--- a/tc/m_xt.c
+++ b/tc/m_xt.c
@@ -298,7 +298,10 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg)
        if (arg == NULL)
                return -1;
 
-       xtables_init_all(&tcipt_globals, NFPROTO_IPV4);
+       /* copy tcipt_globals because .opts will be modified by iptables */
+       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 +336,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 +349,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);