2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 18:07:57 +00:00

net: nftables: avoid restore failure if the CRIU nft table already exist

CRIU locks the network during restore in an "empty" network namespace.
However, "empty" in this context means CRIU isn't restoring the
namespace. This network namespace can be the same namespace where
processes have been dumped and so the network is already locked in it.

Fixes #2650

Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit is contained in:
Andrei Vagin 2025-04-21 06:33:41 +00:00
parent 622b4ed448
commit 75eaa65f81
3 changed files with 19 additions and 15 deletions

View File

@ -2119,7 +2119,7 @@ static int restore_root_task(struct pstree_item *init)
* the '--empty-ns net' mode no iptables C/R is done and we * the '--empty-ns net' mode no iptables C/R is done and we
* need to return these rules by hands. * need to return these rules by hands.
*/ */
ret = network_lock_internal(); ret = network_lock_internal(/* restore = */ true);
if (ret) if (ret)
goto out_kill; goto out_kill;
} }

View File

@ -31,7 +31,7 @@ extern int collect_net_namespaces(bool for_dump);
extern int network_lock(void); extern int network_lock(void);
extern void network_unlock(void); extern void network_unlock(void);
extern int network_lock_internal(void); extern int network_lock_internal(bool restore);
extern struct ns_desc net_ns_desc; extern struct ns_desc net_ns_desc;

View File

@ -3206,12 +3206,12 @@ static inline FILE *redirect_nftables_output(struct nft_ctx *nft)
} }
#endif #endif
static inline int nftables_lock_network_internal(void) static inline int nftables_lock_network_internal(bool restore)
{ {
#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1) #if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1)
cleanup_file FILE *fp = NULL; cleanup_file FILE *fp = NULL;
struct nft_ctx *nft; struct nft_ctx *nft;
int ret = 0; int ret = 0, exit_code = -1;
char table[32]; char table[32];
char buf[128]; char buf[128];
@ -3224,11 +3224,16 @@ static inline int nftables_lock_network_internal(void)
fp = redirect_nftables_output(nft); fp = redirect_nftables_output(nft);
if (!fp) if (!fp)
goto out; goto err2;
snprintf(buf, sizeof(buf), "create table %s", table); snprintf(buf, sizeof(buf), "create table %s", table);
if (NFT_RUN_CMD(nft, buf)) ret = NFT_RUN_CMD(nft, buf);
if (ret) {
/* The network has been locked on dump. */
if (restore && errno == EEXIST)
return 0;
goto err2; goto err2;
}
snprintf(buf, sizeof(buf), "add chain %s output { type filter hook output priority 0; policy drop; }", table); snprintf(buf, sizeof(buf), "add chain %s output { type filter hook output priority 0; policy drop; }", table);
if (NFT_RUN_CMD(nft, buf)) if (NFT_RUN_CMD(nft, buf))
@ -3246,17 +3251,16 @@ static inline int nftables_lock_network_internal(void)
if (NFT_RUN_CMD(nft, buf)) if (NFT_RUN_CMD(nft, buf))
goto err1; goto err1;
goto out; exit_code = 0;
out:
nft_ctx_free(nft);
return exit_code;
err1: err1:
snprintf(buf, sizeof(buf), "delete table %s", table); snprintf(buf, sizeof(buf), "delete table %s", table);
NFT_RUN_CMD(nft, buf); NFT_RUN_CMD(nft, buf);
err2: err2:
ret = -1;
pr_err("Locking network failed using nftables\n"); pr_err("Locking network failed using nftables\n");
out: goto out;
nft_ctx_free(nft);
return ret;
#else #else
pr_err("CRIU was built without libnftables support\n"); pr_err("CRIU was built without libnftables support\n");
return -1; return -1;
@ -3288,7 +3292,7 @@ static int iptables_network_lock_internal(void)
return ret; return ret;
} }
int network_lock_internal(void) int network_lock_internal(bool restore)
{ {
int ret = 0, nsret; int ret = 0, nsret;
@ -3301,7 +3305,7 @@ int network_lock_internal(void)
if (opts.network_lock_method == NETWORK_LOCK_IPTABLES) if (opts.network_lock_method == NETWORK_LOCK_IPTABLES)
ret = iptables_network_lock_internal(); ret = iptables_network_lock_internal();
else if (opts.network_lock_method == NETWORK_LOCK_NFTABLES) else if (opts.network_lock_method == NETWORK_LOCK_NFTABLES)
ret = nftables_lock_network_internal(); ret = nftables_lock_network_internal(restore);
if (restore_ns(nsret, &net_ns_desc)) if (restore_ns(nsret, &net_ns_desc))
ret = -1; ret = -1;
@ -3427,7 +3431,7 @@ int network_lock(void)
if (run_scripts(ACT_NET_LOCK)) if (run_scripts(ACT_NET_LOCK))
return -1; return -1;
return network_lock_internal(); return network_lock_internal(false);
} }
void network_unlock(void) void network_unlock(void)