]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
tc: m_xt: Fix segfault when adding multiple actions at once
authorPhil Sutter <phil@nwl.cc>
Fri, 10 Jun 2016 11:42:01 +0000 (13:42 +0200)
committerStephen Hemminger <shemming@brocade.com>
Tue, 14 Jun 2016 21:35:56 +0000 (14:35 -0700)
Without this, the following call to tc would segfault:

| tc filter add dev d0 parent ffff: u32 match u32 0 0 \
|  action xt -j MARK --set-mark 0x1 \
|  action xt -j MARK --set-mark 0x1

The reason is basically the same as for 6e2e5ec28bad4 ("fix print_ipt:
segfault if more then one filter with action -j MARK.") but in
parse_ipt() instead of print_ipt().

Signed-off-by: Phil Sutter <phil@nwl.cc>
tc/m_xt.c

index 62ec6d7f18e73205d0268e97113a4df75d1475bc..45d86d66248d41d92f0a7dba63dbbf25c997215c 100644 (file)
--- a/tc/m_xt.c
+++ b/tc/m_xt.c
@@ -133,7 +133,9 @@ static int parse_ipt(struct action_util *a, int *argc_p,
        __u32 hook = 0, index = 0;
        struct option *opts = NULL;
 
-       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();
 
        {
@@ -153,7 +155,7 @@ static int parse_ipt(struct action_util *a, int *argc_p,
        }
 
        while (1) {
-               c = getopt_long(argc, argv, "j:", tcipt_globals.opts, NULL);
+               c = getopt_long(argc, argv, "j:", tmp_tcipt_globals.opts, NULL);
                if (c == -1)
                        break;
                switch (c) {
@@ -166,12 +168,12 @@ static int parse_ipt(struct action_util *a, int *argc_p,
                                        return -1;
                                }
 #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
@@ -179,7 +181,7 @@ static int parse_ipt(struct action_util *a, int *argc_p,
                                fprintf(stderr, " failed to find additional 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", optarg);
                                return -1;