Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

criu: Enable support for restore of shared IPC, UTS and Time namespaces #743

Merged
merged 3 commits into from
Oct 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 26 additions & 23 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
AC_PREREQ([2.69])
AC_INIT([crun],
m4_esyscmd([build-aux/git-version-gen --prefix "" .tarball-version]),
[[email protected]])
m4_esyscmd([build-aux/git-version-gen --prefix "" .tarball-version]),
[[email protected]])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
Expand Down Expand Up @@ -33,9 +33,9 @@ AC_ARG_ENABLE(embedded-yajl,
AS_HELP_STRING([--enable-embedded-yajl], [Statically link a modified yajl version]),
[
case "${enableval}" in
yes) embedded_yajl=true ;;
no) embedded_yajl=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-embedded-yajl) ;;
yes) embedded_yajl=true ;;
no) embedded_yajl=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-embedded-yajl) ;;
esac],[embedded_yajl=false])

AM_CONDITIONAL([HAVE_EMBEDDED_YAJL], [test x"$embedded_yajl" == xtrue])
Expand All @@ -57,7 +57,7 @@ AS_IF([test "x$enable_caps" != "xno"], [
dnl dl
AC_ARG_ENABLE([dl], AS_HELP_STRING([--disable-dl], [Disable dynamic libraries support]))
AS_IF([test "x$enable_dl" != "xno"], [
AC_SEARCH_LIBS([dlopen], [dl], [AC_DEFINE([HAVE_DLOPEN], 1, [Define if DLOPEN is available])], [])
AC_SEARCH_LIBS([dlopen], [dl], [AC_DEFINE([HAVE_DLOPEN], 1, [Define if DLOPEN is available])], [])
])

dnl include support for libkrun (EXPERIMENTAL)
Expand Down Expand Up @@ -96,11 +96,11 @@ AS_IF([test "x$enable_bpf" != "xno"], [
#include <unistd.h>
#include <stdint.h>
#include <linux/bpf.h>
void foo() {
void foo() {
uint64_t val = 0x123456789;
union bpf_attr attr;
attr.insns = val;
}
}
int program = BPF_PROG_TYPE_CGROUP_DEVICE;
]])],
[AC_MSG_RESULT(yes)
Expand All @@ -112,22 +112,24 @@ AS_IF([test "x$enable_bpf" != "xno"], [

AC_ARG_WITH([python-bindings], AS_HELP_STRING([--with-python-bindings], [build the Python bindings]))
AS_IF([test "x$with_python_bindings" = "xyes"], [
PKG_CHECK_MODULES([PYTHON], [python3], [], [AC_MSG_ERROR([*** python headers not found])])
# configure should not touch CFLAGS/LDFLAGS but we need it to propagate it
# to libocispec.
CFLAGS+=" -fPIC "
LDFLAGS+=" -fPIC "
PKG_CHECK_MODULES([PYTHON], [python3], [], [AC_MSG_ERROR([*** python headers not found])])
# configure should not touch CFLAGS/LDFLAGS but we need it to propagate it
# to libocispec.
CFLAGS+=" -fPIC "
LDFLAGS+=" -fPIC "
])

dnl criu
AC_ARG_ENABLE([criu], AS_HELP_STRING([--disable-criu], [Disable CRIU based checkpoint/restore support]))
AS_IF([test "x$enable_criu" != "xno"], [
PKG_CHECK_MODULES([CRIU], [criu >= 3.15], [have_criu="yes"], [have_criu="no"
AC_MSG_NOTICE([CRIU headers not found, building without CRIU support])])
AS_IF([test "$have_criu" = "yes"], [
AC_DEFINE([HAVE_CRIU], 1, [Define if CRIU is available])
AC_SEARCH_LIBS(criu_init_opts, [criu])
])
PKG_CHECK_MODULES([CRIU], [criu >= 3.15], [have_criu="yes"], [have_criu="no"
AC_MSG_NOTICE([CRIU headers not found, building without CRIU support])])
PKG_CHECK_MODULES([CRIU], [criu > 3.16], [have_criu_join_ns="yes"], [have_criu_join_ns="no"
AC_MSG_NOTICE([CRIU version doesn't support join-ns API])])
AS_IF([test "$have_criu" = "yes"], [
AC_DEFINE([HAVE_CRIU], 1, [Define if CRIU is available])
AC_SEARCH_LIBS(criu_init_opts, [criu])
])
], [AC_MSG_NOTICE([CRIU support disabled per user request])])

FOUND_LIBS=$LIBS
Expand All @@ -138,10 +140,10 @@ AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([[
#include <linux/mount.h>
int cmd = FSCONFIG_CMD_CREATE;
]])],
[AC_MSG_RESULT(yes)
]])],
[AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_FSCONFIG_CMD_CREATE], 1, [Define if FSCONFIG_CMD_CREATE is available])],
[AC_MSG_RESULT(no)])
[AC_MSG_RESULT(no)])

AC_MSG_CHECKING([for seccomp notify API])
AC_COMPILE_IFELSE(
Expand All @@ -163,13 +165,14 @@ AC_SUBST([RPM_VERSION])

AC_CHECK_TOOL(GPERF, gperf)
if test -z "$GPERF"; then
AC_MSG_NOTICE(gperf not found - cannot rebuild signal parser code)
AC_MSG_NOTICE(gperf not found - cannot rebuild signal parser code)
fi

AC_SEARCH_LIBS([argp_parse], [argp], [], [AC_MSG_ERROR([*** argp functions not found - install libargp or argp_standalone])])

AM_CONDITIONAL([PYTHON_BINDINGS], [test "x$with_python_bindings" = "xyes"])
AM_CONDITIONAL([CRIU_SUPPORT], [test "x$have_criu" = "xyes"])
AM_CONDITIONAL([CRIU_JOIN_NS_SUPPORT], [test "x$have_criu_join_ns" = "xyes"])

AC_CONFIG_FILES([Makefile rpm/crun.spec])

Expand Down
44 changes: 42 additions & 2 deletions src/libcrun/criu.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
# define CRIU_EXT_NETNS "extRootNetNS"
# define CRIU_EXT_PIDNS "extRootPidNS"

# ifndef CLONE_NEWTIME
# define CLONE_NEWTIME 0x00000080 /* New time namespace */
# endif

static const char *console_socket = NULL;

static int
Expand Down Expand Up @@ -645,8 +649,18 @@ libcrun_container_restore_linux_criu (libcrun_container_status_t *status, libcru
goto out_umount;
}

/* If there is a PID or network namespace defined in config.json we are telling
* CRIU to restore the process into that namespace.
# ifdef CRIU_JOIN_NS_SUPPORT
/* criu_join_ns_add() API was introduced with CRIU version 3.16.1
* Here we check if this API is available at build time to support
* compiling with older version of CRIU, and at runtime to support
* running crun with older versions of libcriu.so.2.
*/
bool join_ns_support = criu_check_version (31601) == 1;
rst0git marked this conversation as resolved.
Show resolved Hide resolved
# endif

/* If a namespace defined in config.json we are telling
* CRIU use that namespace when restoring the process tree.
*
* CRIU expects the information about the namespace like this:
* --inherit-fd fd[<fd>]:<key>
* The <key> needs to be the same as during checkpointing (extRootNetNS). */
Expand All @@ -673,6 +687,32 @@ libcrun_container_restore_linux_criu (libcrun_container_status_t *status, libcru

criu_add_inherit_fd (inherit_new_pid_fd, CRIU_EXT_PIDNS);
}

# ifdef CRIU_JOIN_NS_SUPPORT
if (value == CLONE_NEWTIME && def->linux->namespaces[i]->path != NULL)
{
if (join_ns_support)
criu_join_ns_add ("time", def->linux->namespaces[i]->path, NULL);
else
return crun_make_error (err, 0, "Shared time namespace restore is supported in CRIU >= 3.16.1");
}

if (value == CLONE_NEWIPC && def->linux->namespaces[i]->path != NULL)
{
if (join_ns_support)
criu_join_ns_add ("ipc", def->linux->namespaces[i]->path, NULL);
else
return crun_make_error (err, 0, "Shared ipc namespace restore is supported in CRIU >= 3.16.1");
}

if (value == CLONE_NEWUTS && def->linux->namespaces[i]->path != NULL)
{
if (join_ns_support)
criu_join_ns_add ("uts", def->linux->namespaces[i]->path, NULL);
else
return crun_make_error (err, 0, "Shared uts namespace restore is supported in CRIU >= 3.16.1");
}
# endif
}

/* Tell CRIU if cgroup v1 needs to be handled. */
Expand Down
6 changes: 6 additions & 0 deletions tests/test_checkpoint_restore.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ def test_cr_with_ext_ns():
ns.update({'path': os.path.join(ns_path, 'pid')})
if ns['type'] == 'network':
ns.update({'path': os.path.join(ns_path, 'net')})
if ns['type'] == 'ipc':
ns.update({'path': os.path.join(ns_path, 'ipc')})
if ns['type'] == 'uts':
ns.update({'path': os.path.join(ns_path, 'uts')})
if ns['type'] == 'time':
ns.update({'path': os.path.join(ns_path, 'time')})

return run_cr_test(conf)

Expand Down