From c4837104c868142805dbfe1c3f72017d0d71d08f Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 17 Dec 2024 13:00:50 +0100 Subject: [PATCH] net: remember the name of the lock chain (nftables) Using libnftables the chain to lock the network is composed of ("CRIU-%d", real_pid). This leads to around 40 zdtm tests failing with errors like this: Error: No such file or directory; did you mean table 'CRIU-62' in family inet? delete table inet CRIU-86 The reason is that as soon as a process is running in a namespace the real PID can be anything and only the PID in the namespace is restored correctly. Relying on the real PID does not work for the chain name. Using the PID of the innermost namespace would lead to the chain be called 'CRIU-1' most of the time which is also not really unique. The uniqueness of the name was always problematic. With this change all tests are working again which rely on network locking if the nftables backend is used for network locking. Signed-off-by: Adrian Reber --- criu/cr-dump.c | 2 +- criu/cr-restore.c | 2 +- criu/image.c | 4 ++++ criu/include/net.h | 5 +++-- criu/net.c | 26 ++++++++++++++++++-------- images/inventory.proto | 1 + 6 files changed, 28 insertions(+), 12 deletions(-) diff --git a/criu/cr-dump.c b/criu/cr-dump.c index 1bc5d934f5..31a8703de7 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -2195,7 +2195,7 @@ int cr_dump_tasks(pid_t pid) if (collect_pstree_ids()) goto err; - if (network_lock()) + if (network_lock(&he)) goto err; if (rpc_query_external_files()) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 646300bdb8..9437b2ebcd 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -2113,7 +2113,7 @@ static int restore_root_task(struct pstree_item *init) * the '--empty-ns net' mode no iptables C/R is done and we * need to return these rules by hands. */ - ret = network_lock_internal(); + ret = network_lock_internal(NULL); if (ret) goto out_kill; } diff --git a/criu/image.c b/criu/image.c index 9589167fb1..4b74eef130 100644 --- a/criu/image.c +++ b/criu/image.c @@ -25,6 +25,7 @@ bool img_common_magic = true; TaskKobjIdsEntry *root_ids; u32 root_cg_set; Lsmtype image_lsm; +char nft_lock_table[32]; struct inventory_plugin { struct list_head node; @@ -120,6 +121,9 @@ int check_img_inventory(bool restore) goto out_err; } } + + if (he->nft_lock_table) + strncpy(nft_lock_table, he->nft_lock_table, sizeof(nft_lock_table) - 1); } ret = 0; diff --git a/criu/include/net.h b/criu/include/net.h index 5e8a848620..0b0afb0b38 100644 --- a/criu/include/net.h +++ b/criu/include/net.h @@ -29,9 +29,10 @@ struct veth_pair { extern int collect_net_namespaces(bool for_dump); -extern int network_lock(void); +#include "images/inventory.pb-c.h" +extern int network_lock(InventoryEntry *he); extern void network_unlock(void); -extern int network_lock_internal(void); +extern int network_lock_internal(InventoryEntry *he); extern struct ns_desc net_ns_desc; diff --git a/criu/net.c b/criu/net.c index eee3311087..2bfd9bd9de 100644 --- a/criu/net.c +++ b/criu/net.c @@ -229,6 +229,8 @@ static const char *unix_conf_entries[] = { "max_dgram_qlen", }; +extern char nft_lock_table[32]; + /* * MAX_CONF_UNIX_PATH = (sizeof(CONF_UNIX_FMT) - strlen("%s")) * + MAX_CONF_UNIX_OPT_PATH @@ -3066,7 +3068,7 @@ static int iptables_restore(bool ipv6, char *buf, int size) return ret; } -static inline int nftables_lock_network_internal(void) +static inline int nftables_lock_network_internal(InventoryEntry *he) { #if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1) struct nft_ctx *nft; @@ -3077,6 +3079,10 @@ static inline int nftables_lock_network_internal(void) if (nftables_get_table(table, sizeof(table))) return -1; + if (he) { + he->nft_lock_table = strdup(table); + } + nft = nft_ctx_new(NFT_CTX_DEFAULT); if (!nft) return -1; @@ -3143,7 +3149,7 @@ static int iptables_network_lock_internal(void) return ret; } -int network_lock_internal(void) +int network_lock_internal(InventoryEntry *he) { int ret = 0, nsret; @@ -3156,7 +3162,7 @@ int network_lock_internal(void) if (opts.network_lock_method == NETWORK_LOCK_IPTABLES) ret = iptables_network_lock_internal(); else if (opts.network_lock_method == NETWORK_LOCK_NFTABLES) - ret = nftables_lock_network_internal(); + ret = nftables_lock_network_internal(he); if (restore_ns(nsret, &net_ns_desc)) ret = -1; @@ -3172,8 +3178,12 @@ static inline int nftables_network_unlock(void) char table[32]; char buf[128]; - if (nftables_get_table(table, sizeof(table))) - return -1; + if (nft_lock_table[0] != 0) { + strncpy(table, nft_lock_table, sizeof(table)); + } else { + if (nftables_get_table(table, sizeof(table))) + return -1; + } nft = nft_ctx_new(NFT_CTX_DEFAULT); if (!nft) @@ -3263,7 +3273,7 @@ static int network_unlock_internal(void) return ret; } -int network_lock(void) +int network_lock(InventoryEntry *he) { pr_info("Lock network\n"); @@ -3277,10 +3287,10 @@ int network_lock(void) if (run_scripts(ACT_NET_LOCK)) return -1; - return network_lock_internal(); + return network_lock_internal(he); } -void network_unlock(void) +void network_unlock() { pr_info("Unlock network\n"); diff --git a/images/inventory.proto b/images/inventory.proto index 7f655031bc..5d416c202d 100644 --- a/images/inventory.proto +++ b/images/inventory.proto @@ -29,4 +29,5 @@ message inventory_entry { optional bool tcp_close = 10; optional uint32 network_lock_method = 11; optional plugins_entry plugins_entry = 12; + optional string nft_lock_table = 13; }