diff --git a/criu/cr-check.c b/criu/cr-check.c index bcbcf3f2b..e4e590c4d 100644 --- a/criu/cr-check.c +++ b/criu/cr-check.c @@ -1193,7 +1193,7 @@ static int check_ipt_legacy(void) char *ipt_legacy_bin; char *ip6t_legacy_bin; - ipt_legacy_bin = get_legacy_iptables_bin(false); + ipt_legacy_bin = get_legacy_iptables_bin(false, false); if (!ipt_legacy_bin) { pr_warn("Couldn't find iptables version which is using iptables legacy API\n"); return -1; @@ -1204,7 +1204,7 @@ static int check_ipt_legacy(void) if (!kdat.ipv6) return 0; - ip6t_legacy_bin = get_legacy_iptables_bin(true); + ip6t_legacy_bin = get_legacy_iptables_bin(true, false); if (!ip6t_legacy_bin) { pr_warn("Couldn't find ip6tables version which is using iptables legacy API\n"); return -1; diff --git a/criu/include/util.h b/criu/include/util.h index 3a0403113..4b4dfda95 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -384,7 +384,7 @@ static inline void print_stack_trace(pid_t pid) extern int mount_detached_fs(const char *fsname); -extern char *get_legacy_iptables_bin(bool ipv6); +extern char *get_legacy_iptables_bin(bool ipv6, bool restore); extern int set_opts_cap_eff(void); diff --git a/criu/net.c b/criu/net.c index 755a48377..230cc7433 100644 --- a/criu/net.c +++ b/criu/net.c @@ -2039,10 +2039,10 @@ static inline int dump_iptables(struct cr_imgset *fds) * and iptables backend is nft to prevent duplicate dumps. */ #if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1) - iptables_cmd = get_legacy_iptables_bin(false); + iptables_cmd = get_legacy_iptables_bin(false, false); if (kdat.ipv6) - ip6tables_cmd = get_legacy_iptables_bin(true); + ip6tables_cmd = get_legacy_iptables_bin(true, false); #endif if (!iptables_cmd) { @@ -2360,9 +2360,19 @@ static int prepare_xtable_lock(void) static inline int restore_iptables(int pid) { + char *iptables_cmd = "iptables-restore"; + char *ip6tables_cmd = "ip6tables-restore"; + char comm[32]; int ret = -1; struct cr_img *img; +#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1) + iptables_cmd = get_legacy_iptables_bin(false, true); + + if (kdat.ipv6) + ip6tables_cmd = get_legacy_iptables_bin(true, true); +#endif + img = open_image(CR_FD_IPTABLES, O_RSTR, pid); if (img == NULL) return -1; @@ -2372,7 +2382,19 @@ static inline int restore_iptables(int pid) goto ipt6; } - ret = run_iptables_tool("iptables-restore -w", img_raw_fd(img), -1); + if (!iptables_cmd) { + pr_err("Can't restore iptables dump - no legacy version present\n"); + close_image(img); + return -1; + } + + if (snprintf(comm, sizeof(comm), "%s -w", iptables_cmd) >= sizeof(comm)) { + pr_err("Can't fit '%s -w' to buffer\n", iptables_cmd); + close_image(img); + return -1; + } + + ret = run_iptables_tool(comm, img_raw_fd(img), -1); close_image(img); if (ret) return ret; @@ -2383,7 +2405,19 @@ ipt6: if (empty_image(img)) goto out; - ret = run_iptables_tool("ip6tables-restore -w", img_raw_fd(img), -1); + if (!ip6tables_cmd) { + pr_err("Can't restore ip6tables dump - no legacy version present\n"); + close_image(img); + return -1; + } + + if (snprintf(comm, sizeof(comm), "%s -w", ip6tables_cmd) >= sizeof(comm)) { + pr_err("Can't fit '%s -w' to buffer\n", ip6tables_cmd); + close_image(img); + return -1; + } + + ret = run_iptables_tool(comm, img_raw_fd(img), -1); out: close_image(img); diff --git a/criu/util.c b/criu/util.c index 959e60938..db96cf938 100644 --- a/criu/util.c +++ b/criu/util.c @@ -1594,44 +1594,46 @@ err: return ret; } -char *get_legacy_iptables_bin(bool ipv6) +char *get_legacy_iptables_bin(bool ipv6, bool restore) { - static char iptables_bin[2][32]; + static char iptables_bin[2][2][32]; /* 0 - means we don't know yet, * -1 - not present, * 1 - present. */ - static int iptables_present[2] = { 0, 0 }; - char bins[2][2][32] = { { "iptables-save", "iptables-legacy-save" }, - { "ip6tables-save", "ip6tables-legacy-save" } }; + static int iptables_present[2][2] = { { 0, 0 }, { 0, 0 } }; + char bins[2][2][2][32] = { { { "iptables-save", "iptables-legacy-save" }, + { "iptables-restore", "iptables-legacy-restore" } }, + { { "ip6tables-save", "ip6tables-legacy-save" }, + { "ip6tables-restore", "ip6tables-legacy-restore" } } }; int ret; - if (iptables_present[ipv6] == -1) + if (iptables_present[ipv6][restore] == -1) return NULL; - if (iptables_present[ipv6] == 1) - return iptables_bin[ipv6]; + if (iptables_present[ipv6][restore] == 1) + return iptables_bin[ipv6][restore]; - memcpy(iptables_bin[ipv6], bins[ipv6][0], strlen(bins[ipv6][0]) + 1); - ret = is_iptables_nft(iptables_bin[ipv6]); + memcpy(iptables_bin[ipv6][restore], bins[ipv6][restore][0], strlen(bins[ipv6][restore][0]) + 1); + ret = is_iptables_nft(iptables_bin[ipv6][restore]); /* * iptables on host uses nft backend (or not installed), * let's try iptables-legacy */ if (ret < 0 || ret == 1) { - memcpy(iptables_bin[ipv6], bins[ipv6][1], strlen(bins[ipv6][1]) + 1); - ret = is_iptables_nft(iptables_bin[ipv6]); + memcpy(iptables_bin[ipv6][restore], bins[ipv6][restore][1], strlen(bins[ipv6][restore][1]) + 1); + ret = is_iptables_nft(iptables_bin[ipv6][restore]); if (ret < 0 || ret == 1) { - iptables_present[ipv6] = -1; + iptables_present[ipv6][restore] = -1; return NULL; } } /* we can come here with iptables-save or iptables-legacy-save */ - iptables_present[ipv6] = 1; + iptables_present[ipv6][restore] = 1; - return iptables_bin[ipv6]; + return iptables_bin[ipv6][restore]; } /*