>From 2be366b5b534af61756e1eb69e26fcf9c4544aa7 Mon Sep 17 00:00:00 2001 From: Andreas Greve 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 --- 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