From: Andreas Greve Date: Sat, 10 May 2014 09:19:18 +0000 (+0200) Subject: fix print_ipt: segfault if more then one filter with action -j MARK. X-Git-Tag: v3.15.0~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e2e5ec28bad4561c534adf4f22b2706e385c71d;p=thirdparty%2Fiproute2.git fix 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 --- diff --git a/tc/m_xt.c b/tc/m_xt.c index 27029c1b5..3b0cf95b4 100644 --- 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);