criu: add nftables netns-wide locking/unlocking

This adds nftables based internal network locking as an
alernative for iptables. This avoid the external dependency
of iptables-restore.

v2: fix indentation & rename 'free' lable to 'out'
v3: add better message when CRIU is build without libnftables support
v4:
	- move 'ret = -1' below err: lable to avoid redundancy
	- fix nft ctx memory leak in case of success in
	  nftables_network_unlock()
v5: add better error message on lock failure

Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
This commit is contained in:
Zeyad Yasser 2021-07-09 16:36:23 +02:00 committed by Andrei Vagin
parent f246ca56c0
commit 19cc0bfa65

View file

@ -45,6 +45,7 @@
#include "util.h"
#include "external.h"
#include "fdstore.h"
#include "netfilter.h"
#include "protobuf.h"
#include "images/netdev.pb-c.h"
@ -3014,6 +3015,47 @@ err:
return ret;
}
static inline int nftables_lock_network_internal(void)
{
#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1)
struct nft_ctx *nft;
int ret = 0;
nft = nft_ctx_new(NFT_CTX_DEFAULT);
if (!nft)
return -1;
if (NFT_RUN_CMD(nft, "add table inet CRIU"))
goto err2;
if (NFT_RUN_CMD(nft, "add chain inet CRIU output { type filter hook output priority 0; policy drop; }"))
goto err1;
if (NFT_RUN_CMD(nft, "add rule inet CRIU output meta mark " __stringify(SOCCR_MARK) " accept"))
goto err1;
if (NFT_RUN_CMD(nft, "add chain inet CRIU input { type filter hook input priority 0; policy drop; }"))
goto err1;
if (NFT_RUN_CMD(nft, "add rule inet CRIU input meta mark " __stringify(SOCCR_MARK) " accept"))
goto err1;
goto out;
err1:
NFT_RUN_CMD(nft, "delete table inet CRIU");
err2:
ret = -1;
pr_err("Locking network failed using nftables\n");
out:
nft_ctx_free(nft);
return ret;
#else
pr_err("CRIU was built without libnftables support\n");
return -1;
#endif
}
static int iptables_network_lock_internal(void)
{
char conf[] = "*filter\n"
@ -3048,6 +3090,8 @@ 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();
if (restore_ns(nsret, &net_ns_desc))
ret = -1;
@ -3055,6 +3099,27 @@ int network_lock_internal(void)
return ret;
}
static inline int nftables_network_unlock(void)
{
#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1)
int ret = 0;
struct nft_ctx *nft;
nft = nft_ctx_new(NFT_CTX_DEFAULT);
if (!nft)
return -1;
if (NFT_RUN_CMD(nft, "delete table inet CRIU"))
ret = -1;
nft_ctx_free(nft);
return ret;
#else
pr_err("CRIU was built without libnftables support\n");
return -1;
#endif
}
static int iptables_network_unlock_internal(void)
{
char conf[] = "*filter\n"
@ -3081,6 +3146,8 @@ static int network_unlock_internal(void)
if (opts.network_lock_method == NETWORK_LOCK_IPTABLES)
ret = iptables_network_unlock_internal();
else if (opts.network_lock_method == NETWORK_LOCK_NFTABLES)
ret = nftables_network_unlock();
if (restore_ns(nsret, &net_ns_desc))
ret = -1;