net: use get_legacy_iptables_bin also on restore

Without this we might try to restore iptables legacy images with
iptables nft.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This commit is contained in:
Pavel Tikhomirov 2023-02-03 12:53:00 +08:00 committed by Andrei Vagin
parent 2982867185
commit 42c4be2a92
4 changed files with 58 additions and 22 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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];
}
/*