From c4f8c87a7a06fdc46e10fff129d89f8753d62380 Mon Sep 17 00:00:00 2001 From: Danish Prakash Date: Thu, 5 Dec 2024 14:59:47 +0530 Subject: [PATCH] checkpoint/restore: allow passing network lock method to libcriu Netavark defaults to nftables but it seems that crun checkpoint doesn't allow setting firewall driver used for network locking and unlocking by criu. criu defaults to iptables and in situations where podman is installed without iptables, criu tries to use iptable utils and fails. Signed-off-by: Danish Prakash --- configure.ac | 6 ++++++ src/checkpoint.c | 25 +++++++++++++++++++++++++ src/checkpoint.h | 1 + src/libcrun/container.h | 1 + src/libcrun/criu.c | 6 ++++++ src/restore.c | 6 ++++++ 6 files changed, 45 insertions(+) diff --git a/configure.ac b/configure.ac index 1ba5b61bfc..7628a93066 100644 --- a/configure.ac +++ b/configure.ac @@ -252,6 +252,8 @@ AS_IF([test "x$enable_criu" != "xno"], [ AC_MSG_NOTICE([CRIU version doesn't support join-ns API])]) PKG_CHECK_MODULES([CRIU_PRE_DUMP], [criu > 3.16.1], [have_criu_pre_dump="yes"], [have_criu_pre_dump="no" AC_MSG_NOTICE([CRIU version doesn't support for pre-dumping])]) + PKG_CHECK_MODULES([CRIU_NETWORK_LOCK_SKIP], [criu >= 3.19], [have_criu_network_lock_skip="yes"], [have_criu_network_lock_skip="no" + AC_MSG_NOTICE([CRIU version doesn't support CRIU_NETWORK_LOCK_SKIP])]) AS_IF([test "$have_criu" = "yes"], [ AC_DEFINE([HAVE_CRIU], 1, [Define if CRIU is available]) ]) @@ -261,6 +263,10 @@ AS_IF([test "x$enable_criu" != "xno"], [ AS_IF([test "$have_criu_pre_dump" = "yes"], [ AC_DEFINE([CRIU_PRE_DUMP_SUPPORT], 1, [Define if CRIU pre-dump support is available]) ]) + AS_IF([test "$have_criu_network_lock_skip" = "yes"], [ + AC_DEFINE([CRIU_NETWORK_LOCK_SKIP_SUPPORT], 1, [Define if CRIU_NETWORK_LOCK_SKIP is available]) + ]) + ], [AC_MSG_NOTICE([CRIU support disabled per user request])]) FOUND_LIBS=$LIBS diff --git a/src/checkpoint.c b/src/checkpoint.c index 0cee27ac18..c734193d69 100644 --- a/src/checkpoint.c +++ b/src/checkpoint.c @@ -44,6 +44,7 @@ enum OPTION_SHELL_JOB, OPTION_EXT_UNIX_SK, OPTION_FILE_LOCKS, + OPTION_NETWORK_LOCK_METHOD, OPTION_PARENT_PATH, OPTION_PRE_DUMP, OPTION_MANAGE_CGROUPS_MODE, @@ -61,6 +62,7 @@ static struct argp_option options[] { "ext-unix-sk", OPTION_EXT_UNIX_SK, 0, 0, "allow external unix sockets", 0 }, { "shell-job", OPTION_SHELL_JOB, 0, 0, "allow shell jobs", 0 }, { "file-locks", OPTION_FILE_LOCKS, 0, 0, "allow file locks", 0 }, + { "network-lock", OPTION_NETWORK_LOCK_METHOD, 0, 0, "set network lock method", 0 }, #ifdef CRIU_PRE_DUMP_SUPPORT { "parent-path", OPTION_PARENT_PATH, "DIR", 0, "path for previous criu image files in pre-dump", 0 }, { "pre-dump", OPTION_PRE_DUMP, 0, 0, "dump container's memory information only, leave the container running after this", 0 }, @@ -72,6 +74,25 @@ static struct argp_option options[] static char args_doc[] = "checkpoint CONTAINER"; +int +crun_parse_network_lock_method (char *param arg_unused) +{ +#if HAVE_CRIU && HAVE_DLOPEN + if (strcmp (param, "iptables") == 0) + return CRIU_NETWORK_LOCK_IPTABLES; + else if (strcmp (param, "nftables") == 0) + return CRIU_NETWORK_LOCK_NFTABLES; +# if CRIU_NETWORK_LOCK_SKIP_SUPPORT + else if (strcmp (param, "skip") == 0) + return CRIU_NETWORK_LOCK_SKIP; +# endif + else + libcrun_fail_with_error (0, "unknown network lock method specified"); +#else + return 0; +#endif +} + int crun_parse_manage_cgroups_mode (char *param arg_unused) { @@ -139,6 +160,10 @@ parse_opt (int key, char *arg, struct argp_state *state) cr_options.manage_cgroups_mode = crun_parse_manage_cgroups_mode (argp_mandatory_argument (arg, state)); break; + case OPTION_NETWORK_LOCK_METHOD: + cr_options.network_lock_method = crun_parse_network_lock_method (argp_mandatory_argument (arg, state)); + break; + default: return ARGP_ERR_UNKNOWN; } diff --git a/src/checkpoint.h b/src/checkpoint.h index 21230a2c42..8a34096b18 100644 --- a/src/checkpoint.h +++ b/src/checkpoint.h @@ -21,6 +21,7 @@ #include "crun.h" int crun_parse_manage_cgroups_mode (char *param); +int crun_parse_network_lock_method (char *param); int crun_command_checkpoint (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); #endif diff --git a/src/libcrun/container.h b/src/libcrun/container.h index a800363317..ccae7bf473 100644 --- a/src/libcrun/container.h +++ b/src/libcrun/container.h @@ -187,6 +187,7 @@ struct libcrun_checkpoint_restore_s char *parent_path; bool pre_dump; int manage_cgroups_mode; + int network_lock_method; char *lsm_profile; char *lsm_mount_context; }; diff --git a/src/libcrun/criu.c b/src/libcrun/criu.c index be2ed43fbc..2e4e0d9daa 100644 --- a/src/libcrun/criu.c +++ b/src/libcrun/criu.c @@ -79,6 +79,7 @@ struct libcriu_wrapper_s void (*criu_set_leave_running) (bool leave_running); void (*criu_set_manage_cgroups) (bool manage); void (*criu_set_manage_cgroups_mode) (enum criu_cg_mode mode); + void (*criu_set_network_lock) (enum criu_network_lock_method method); void (*criu_set_notify_cb) (int (*cb) (char *action, criu_notify_arg_t na)); void (*criu_set_orphan_pts_master) (bool orphan_pts_master); void (*criu_set_images_dir_fd) (int fd); @@ -163,6 +164,7 @@ load_wrapper (struct libcriu_wrapper_s **wrapper_out, libcrun_error_t *err) LOAD_CRIU_FUNCTION (criu_set_log_level, false); LOAD_CRIU_FUNCTION (criu_set_manage_cgroups, false); LOAD_CRIU_FUNCTION (criu_set_manage_cgroups_mode, false); + LOAD_CRIU_FUNCTION (criu_set_network_lock, true); LOAD_CRIU_FUNCTION (criu_set_notify_cb, false); LOAD_CRIU_FUNCTION (criu_set_orphan_pts_master, false); LOAD_CRIU_FUNCTION (criu_set_parent_images, false); @@ -645,6 +647,9 @@ libcrun_container_checkpoint_linux_criu (libcrun_container_status_t *status, lib libcriu_wrapper->criu_set_manage_cgroups_mode (cr_options->manage_cgroups_mode); libcriu_wrapper->criu_set_manage_cgroups (true); + if (libcriu_wrapper->criu_set_network_lock) + libcriu_wrapper->criu_set_network_lock (cr_options->network_lock_method); + ret = libcriu_wrapper->criu_dump (); if (UNLIKELY (ret != 0)) return crun_make_error (err, 0, @@ -979,6 +984,7 @@ libcrun_container_restore_linux_criu (libcrun_container_status_t *status, libcru libcriu_wrapper->criu_set_file_locks (cr_options->file_locks); libcriu_wrapper->criu_set_orphan_pts_master (true); libcriu_wrapper->criu_set_manage_cgroups (true); + libcriu_wrapper->criu_set_network_lock (cr_options->network_lock_method); libcriu_wrapper->criu_set_log_level (4); libcriu_wrapper->criu_set_log_file (CRIU_RESTORE_LOG_FILE); diff --git a/src/restore.c b/src/restore.c index f83f1fb13a..cb8fad2efc 100644 --- a/src/restore.c +++ b/src/restore.c @@ -44,6 +44,7 @@ enum OPTION_CONSOLE_SOCKET, OPTION_FILE_LOCKS, OPTION_MANAGE_CGROUPS_MODE, + OPTION_NETWORK_LOCK_METHOD, OPTION_LSM_PROFILE, OPTION_LSM_MOUNT_CONTEXT, }; @@ -69,6 +70,7 @@ static struct argp_option options[] "path to a socket that will receive the ptmx end of the tty", 0 }, { "file-locks", OPTION_FILE_LOCKS, 0, 0, "allow file locks", 0 }, { "manage-cgroups-mode", OPTION_MANAGE_CGROUPS_MODE, "MODE", 0, "cgroups mode: 'soft' (default), 'ignore', 'full' and 'strict'", 0 }, + { "network-lock", OPTION_NETWORK_LOCK_METHOD, 0, 0, "set network lock method", 0 }, { "lsm-profile", OPTION_LSM_PROFILE, "VALUE", 0, "Specify an LSM profile to be used during restore in the form of TYPE:NAME", 0 }, { "lsm-mount-context", OPTION_LSM_MOUNT_CONTEXT, "VALUE", 0, "Specify an LSM mount context to be used during restore", 0 }, { @@ -129,6 +131,10 @@ parse_opt (int key, char *arg, struct argp_state *state) cr_options.manage_cgroups_mode = crun_parse_manage_cgroups_mode (argp_mandatory_argument (arg, state)); break; + case OPTION_NETWORK_LOCK_METHOD: + cr_options.network_lock_method = crun_parse_network_lock_method (argp_mandatory_argument (arg, state)); + break; + case OPTION_LSM_PROFILE: cr_options.lsm_profile = argp_mandatory_argument (arg, state); break;