diff --git a/criu/cr-check.c b/criu/cr-check.c index 8fab51ca4..3575fb3b3 100644 --- a/criu/cr-check.c +++ b/criu/cr-check.c @@ -1362,6 +1362,16 @@ static int check_ns_pid(void) return 0; } +static int check_network_lock_nftables(void) +{ + if (!kdat.has_nftables_concat) { + pr_warn("Nftables based locking requires libnftables and set concatenations support\n"); + return -1; + } + + return 0; +} + static int (*chk_feature)(void); /* @@ -1479,6 +1489,7 @@ int cr_check(void) ret |= check_pidfd_store(); ret |= check_ns_pid(); ret |= check_apparmor_stacking(); + ret |= check_network_lock_nftables(); } /* @@ -1590,6 +1601,7 @@ static struct feature_list feature_list[] = { { "pidfd_store", check_pidfd_store }, { "ns_pid", check_ns_pid }, { "apparmor_stacking", check_apparmor_stacking }, + { "network_lock_nftables", check_network_lock_nftables }, { NULL, NULL }, }; diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h index b2f5d4305..80bad7f11 100644 --- a/criu/include/kerndat.h +++ b/criu/include/kerndat.h @@ -73,6 +73,7 @@ struct kerndat_s { bool has_pidfd_open; bool has_pidfd_getfd; bool has_nspid; + bool has_nftables_concat; }; extern struct kerndat_s kdat; diff --git a/criu/include/netfilter.h b/criu/include/netfilter.h index 35ef26205..5f58c41b7 100644 --- a/criu/include/netfilter.h +++ b/criu/include/netfilter.h @@ -10,4 +10,12 @@ extern int nf_unlock_connection_info(struct inet_sk_info *); extern void preload_netfilter_modules(void); +#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) +#define NFT_RUN_CMD(nft, cmd) nft_run_cmd_from_buffer(nft, cmd, strlen(cmd)) +#elif defined(CONFIG_HAS_NFTABLES_LIB_API_1) +#define NFT_RUN_CMD(nft, cmd) nft_run_cmd_from_buffer(nft, cmd) +#else +#define NFT_RUN_CMD(nft, cmd) BUILD_BUG_ON(1) +#endif + #endif /* __CR_NETFILTER_H__ */ diff --git a/criu/kerndat.c b/criu/kerndat.c index 4d28dac98..da3732261 100644 --- a/criu/kerndat.c +++ b/criu/kerndat.c @@ -14,6 +14,10 @@ #include #include +#if defined(CONFIG_HAS_NFTABLES_LIB_API_0) || defined(CONFIG_HAS_NFTABLES_LIB_API_1) +#include +#endif + #include "common/config.h" #include "int.h" #include "log.h" @@ -1146,6 +1150,39 @@ close: return ret; } +static int kerndat_has_nftables_concat(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")) { + ret = -1; + goto nft_ctx_free_out; + } + + if (NFT_RUN_CMD(nft, "add set inet CRIU conn { type ipv4_addr . inet_service ;}")) + kdat.has_nftables_concat = false; + else + kdat.has_nftables_concat = true; + + /* Clean up */ + NFT_RUN_CMD(nft, "delete table inet CRIU"); + +nft_ctx_free_out: + nft_ctx_free(nft); + return ret; +#else + pr_warn("CRIU was built without libnftables support\n"); + kdat.has_nftables_concat = false; + return 0; +#endif +} + int kerndat_init(void) { int ret; @@ -1293,6 +1330,10 @@ int kerndat_init(void) pr_err("kerndat_has_nspid failed when initializing kerndat.\n"); ret = -1; } + if (!ret && kerndat_has_nftables_concat()) { + pr_err("kerndat_has_nftables_concat failed when initializing kerndat.\n"); + ret = -1; + } kerndat_lsm(); kerndat_mmap_min_addr();