[PATCH] iptables: Fix crash with iptables >= 1.8.11
LiangCheng Wang <[email protected]> Wed, 8 Jul 2026 11:39:26 +0800
| Newsgroups | dev.linux.lists.connman |
|---|---|
| Message-ID | <[email protected]> |
Since iptables 1.8.11, xtables_merge_options() calls xtables_free_opts(), which unconditionally free()s xt_params->opts. ConnMan points opts at the static iptables_opts[] array, so the first option merge for a target or match with extra options (e.g. the MASQUERADE target when enabling tethering) aborts the daemon: free(): invalid pointer connmand[1223]: Aborting (signal 6) [/usr/sbin/connmand] with the invalid free happening inside libxtables.so.12 called from prepare_target(). Fix this by keeping xt_params->opts as a heap-allocated copy of orig_opts at all times, so that libxtables is free to release and replace it. This stays compatible with older iptables versions, where xtables_free_opts() only frees opts when it differs from orig_opts. Reproduced with ConnMan 1.43 and iptables 1.8.11 by enabling WiFi tethering. Same issue reported in Debian bug #1112242 against ConnMan 1.45 and Bluetooth tethering. Signed-off-by: LiangCheng Wang <[email protected]> --- src/iptables.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/iptables.c b/src/iptables.c index a81a0779..956a5b6b 100644 --- a/src/iptables.c +++ b/src/iptables.c @@ -3541,6 +3541,23 @@ static int setup_xtables(int type) return err; } +static struct option *dup_orig_opts(const struct option *orig_opts) +{ + struct option *opts; + unsigned int i; + + for (i = 0; orig_opts[i].name; i++) + ; + + opts = g_try_malloc0(sizeof(struct option) * (i + 1)); + if (!opts) + return NULL; + + memcpy(opts, orig_opts, sizeof(struct option) * i); + + return opts; +} + static void reset_xtables(void) { struct xtables_match *xt_m; @@ -3566,11 +3583,17 @@ static void reset_xtables(void) * We need also to free the memory implicitly allocated * during parsing (see xtables_options_xfrm()). * Note xt_params is actually iptables_globals. + * + * Since iptables 1.8.11 xtables_merge_options() calls + * xtables_free_opts(), which unconditionally free()s + * xt_params->opts. Therefore opts must never point at the + * static orig_opts array; keep it as a heap-allocated copy + * that libxtables is free to release. */ - if (xt_params->opts != xt_params->orig_opts) { + if (xt_params->opts != xt_params->orig_opts) g_free(xt_params->opts); - xt_params->opts = xt_params->orig_opts; - } + + xt_params->opts = dup_orig_opts(xt_params->orig_opts); xt_params->option_offset = 0; } -- 2.34.1