Skip to content

Commit

Permalink
net: remember the name of the lock chain (nftables)
Browse files Browse the repository at this point in the history
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 <areber@redhat.com>
  • Loading branch information
adrianreber committed Dec 17, 2024
1 parent 32d5a76 commit 0305093
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 11 deletions.
2 changes: 1 addition & 1 deletion criu/cr-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
2 changes: 1 addition & 1 deletion criu/cr-restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions criu/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions criu/include/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
48 changes: 41 additions & 7 deletions criu/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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");

Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions images/inventory.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit 0305093

Please sign in to comment.