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..8b34bd6ded 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,21 +3068,34 @@ 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; int ret = 0; char table[32]; char buf[128]; + FILE *fp; 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; + fp = fdopen(log_get_fd(), "w"); + if (!fp) { + pr_perror("fdopen() failed"); + goto err3; + } + nft_ctx_set_output(nft, fp); + nft_ctx_set_error(nft, fp); + snprintf(buf, sizeof(buf), "create table %s", table); if (NFT_RUN_CMD(nft, buf)) goto err2; @@ -3107,6 +3122,9 @@ static inline int nftables_lock_network_internal(void) snprintf(buf, sizeof(buf), "delete table %s", table); NFT_RUN_CMD(nft, buf); err2: + fflush(fp); + fclose(fp); +err3: ret = -1; pr_err("Locking network failed using nftables\n"); out: @@ -3143,7 +3161,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 +3174,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; @@ -3171,18 +3189,34 @@ static inline int nftables_network_unlock(void) struct nft_ctx *nft; char table[32]; char buf[128]; + FILE *fp; - 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) return -1; + fp = fdopen(log_get_fd(), "w"); + if (!fp) { + pr_perror("fdopen() failed"); + nft_ctx_free(nft); + return -1; + } + nft_ctx_set_output(nft, fp); + nft_ctx_set_error(nft, fp); + snprintf(buf, sizeof(buf), "delete table %s", table); if (NFT_RUN_CMD(nft, buf)) ret = -1; + fflush(fp); + fclose(fp); nft_ctx_free(nft); return ret; #else @@ -3263,7 +3297,7 @@ static int network_unlock_internal(void) return ret; } -int network_lock(void) +int network_lock(InventoryEntry *he) { pr_info("Lock network\n"); @@ -3277,7 +3311,7 @@ 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) 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; }