From 48c6bb99300be495476e0e164d5a85da6439b605 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 4 Feb 2025 15:50:02 +0000 Subject: [PATCH 1/7] make: allow setting the default network locking backend As different Linux distributions are switching away from iptables to nftables, this makes it easier to compile CRIU with a different default network locking backend. Instead of changing the source code it is now possible to select the nft backend like this: make NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES Signed-off-by: Adrian Reber --- Makefile | 4 ++++ criu/include/cr_options.h | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/Makefile b/Makefile index 60b78a0749..59bf7c12c2 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,10 @@ ifneq ($(GCOV),) CFLAGS += $(CFLAGS-GCOV) endif +ifneq ($(NETWORK_LOCK_DEFAULT),) + CFLAGS += -DNETWORK_LOCK_DEFAULT=$(NETWORK_LOCK_DEFAULT) +endif + ifeq ($(ASAN),1) CFLAGS-ASAN := -fsanitize=address export CFLAGS-ASAN diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h index 60cf9437e6..ab0bd8fa36 100644 --- a/criu/include/cr_options.h +++ b/criu/include/cr_options.h @@ -70,7 +70,15 @@ enum NETWORK_LOCK_METHOD { NETWORK_LOCK_SKIP, }; +/** + * CRIU currently defaults to the iptables locking backend. + * + * It is, however, possible to change this by defining + * NETWORK_LOCK_DEFAULT to a different value on the command-line. + */ +#ifndef NETWORK_LOCK_DEFAULT #define NETWORK_LOCK_DEFAULT NETWORK_LOCK_IPTABLES +#endif /* * Ghost file size we allow to carry by default. From 18aef1d1e8ba012c7637af6f2d652d8145220309 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 4 Feb 2025 15:56:27 +0000 Subject: [PATCH 2/7] docs: update INSTALL.md with a section about building CRIU The building section also contains the information how to change the network locking backend without source code changes. Signed-off-by: Adrian Reber --- INSTALL.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/INSTALL.md b/INSTALL.md index d786d06eb6..76ace5b023 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,3 +1,23 @@ +## Building CRIU from source code + +First, you need to install compile-time dependencies. Check [Installation dependencies](https://criu.org/Installation#Dependencies) for more info. + +To compile CRIU, run: +``` +make +``` +This should create the `./criu/criu` executable. + +To change the default behaviour of CRIU, the following variables can be passed +to the make command: + + * **NETWORK_LOCK_DEFAULT**, can be set to one of the following + values: `NETWORK_LOCK_IPTABLES`, `NETWORK_LOCK_NFTABLES`, + `NETWORK_LOCK_SKIP`. CRIU defaults to `NETWORK_LOCK_IPTABLES` + if nothing is specified. If another network locking backend is + needed, `make` can be called like this: + `make NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES` + ## Installing CRIU from source code Once CRIU is built one can easily setup the complete CRIU package From 5b0328b5907a6ec3d72baf1db1ddaf095d07bdc4 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 4 Feb 2025 15:57:47 +0000 Subject: [PATCH 3/7] docs: mark make commands with same format as elsewhere This uses the same formatting for the make command examples as seen in README.md. Signed-off-by: Adrian Reber --- INSTALL.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 76ace5b023..af07025186 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -23,9 +23,9 @@ to the make command: Once CRIU is built one can easily setup the complete CRIU package (which includes executable itself, CRIT tool, libraries, manual and etc) simply typing - - make install - +``` +make install +``` this command accepts the following variables: * **DESTDIR**, to specify global root where all components will be placed under (empty by default); @@ -36,17 +36,17 @@ this command accepts the following variables: * **LIBDIR**, to specify directory where to put libraries (guess the correct path by default). Thus one can type - - make DESTDIR=/some/new/place install - +``` +make DESTDIR=/some/new/place install +``` and get everything installed under `/some/new/place`. ## Uninstalling CRIU To clean up previously installed CRIU instance one can type - - make uninstall - +``` +make uninstall +``` and everything should be removed. Note though that if some variable (**DESTDIR**, **BINDIR** and such) has been used during installation procedure, the same *must* be passed with uninstall action. From d6cbd474d7810f592642a6c5f0b1d133891b9807 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 6 Feb 2025 07:34:26 +0000 Subject: [PATCH 4/7] test: others/rpc do not use nftables locking backend The tests in others/rpc are running as non-root and fail silently if the nftables network locking backend is used. This switches those tests to skip the network locking. Signed-off-by: Adrian Reber --- test/others/rpc/errno.py | 2 ++ test/others/rpc/ps_test.py | 1 + test/others/rpc/run.sh | 2 +- test/others/rpc/test-c.c | 2 ++ test/others/rpc/test.py | 1 + 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/test/others/rpc/errno.py b/test/others/rpc/errno.py index b600b6d1c4..4ea6c9d441 100755 --- a/test/others/rpc/errno.py +++ b/test/others/rpc/errno.py @@ -67,6 +67,7 @@ def no_process(self): req = self.get_base_req() req.type = rpc.DUMP req.opts.pid = pid + req.opts.network_lock = rpc.SKIP self.send_req(req) resp = self.recv_resp() @@ -84,6 +85,7 @@ def process_exists(self): req = self.get_base_req() req.type = rpc.DUMP req.opts.leave_running = True + req.opts.network_lock = rpc.SKIP self.send_req(req) resp = self.recv_resp() diff --git a/test/others/rpc/ps_test.py b/test/others/rpc/ps_test.py index daeda49bce..259f22e775 100755 --- a/test/others/rpc/ps_test.py +++ b/test/others/rpc/ps_test.py @@ -23,6 +23,7 @@ req.opts.log_file = 'page-server.log' req.opts.log_level = 4 req.opts.images_dir_fd = os.open(args['dir'], os.O_DIRECTORY) +req.opts.network_lock = rpc.SKIP s.send(req.SerializeToString()) diff --git a/test/others/rpc/run.sh b/test/others/rpc/run.sh index afd4fb5e33..3d5a53ae66 100755 --- a/test/others/rpc/run.sh +++ b/test/others/rpc/run.sh @@ -51,7 +51,7 @@ function test_restore_loop { title_print "Dump loop process" # So theoretically '-j' (--shell-job) should not be necessary, but on alpine # this test fails without it. - ${CRIU} dump -j -v4 -o dump-loop.log -D build/imgs_loop -t ${P} + ${CRIU} dump -j -v4 -o dump-loop.log --network-lock skip -D build/imgs_loop -t ${P} title_print "Run restore-loop" ./restore-loop.py build/criu_service.socket build/imgs_loop diff --git a/test/others/rpc/test-c.c b/test/others/rpc/test-c.c index 792dbbf9c9..b3507975f8 100644 --- a/test/others/rpc/test-c.c +++ b/test/others/rpc/test-c.c @@ -99,6 +99,8 @@ int main(int argc, char *argv[]) req.opts->images_dir_fd = dir_fd; req.opts->has_log_level = true; req.opts->log_level = 4; + req.opts->has_network_lock = true; + req.opts->network_lock = CRIU_NETWORK_LOCK_METHOD__SKIP; /* * Connect to service socket diff --git a/test/others/rpc/test.py b/test/others/rpc/test.py index ce8411bc60..6f692f7557 100755 --- a/test/others/rpc/test.py +++ b/test/others/rpc/test.py @@ -24,6 +24,7 @@ req.opts.leave_running = True req.opts.log_level = 4 req.opts.images_dir_fd = os.open(args['dir'], os.O_DIRECTORY) +req.opts.network_lock = rpc.SKIP # Send request s.send(req.SerializeToString()) From ab05687ecf3760fad7adeaf37b52c9e0362a4710 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 6 Feb 2025 09:57:52 +0000 Subject: [PATCH 5/7] test: print out logs if tests fail If the tests in others/rpc are failing no information about that error can be seen in a CI run. This change displays the log files if the test fails. Signed-off-by: Adrian Reber --- test/others/rpc/Makefile | 10 +++++++++- test/others/rpc/run.sh | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/test/others/rpc/Makefile b/test/others/rpc/Makefile index 69537bb0d3..b2f907abee 100644 --- a/test/others/rpc/Makefile +++ b/test/others/rpc/Makefile @@ -8,9 +8,17 @@ PYTHON ?= python3 run: all @make -C .. loop - mkdir -p build + mkdir -p build/{imgs_errno,imgs_ps,imgs_c,imgs_loop,imgs_py} chmod a+rwx build + chmod a+rwx build/{imgs_errno,imgs_ps,imgs_c,imgs_loop,imgs_py} rm -f build/status + @# Create all log files to be accessible for anybody + @# so that they can be displayed by any user. + for i in imgs_errno/criu.log imgs_ps/page-server.log imgs_ps/dump.log \ + imgs_c/restore-c.log imgs_loop/criu.log imgs_loop/dump-loop.log \ + imgs_py/criu.log imgs_py/restore-py.log imgs_c/criu.log service.log; do \ + touch build/$$i; chmod 666 build/$$i; \ + done sudo -g '#1000' -u '#1000' mkfifo build/status @# Need to start the criu daemon here to access the pidfile. @# The script read.py is used to wait until 'criu service' diff --git a/test/others/rpc/run.sh b/test/others/rpc/run.sh index 3d5a53ae66..b6158dfea5 100755 --- a/test/others/rpc/run.sh +++ b/test/others/rpc/run.sh @@ -3,6 +3,7 @@ set -e CRIU=./criu +FAIL=1 export PROTODIR=`readlink -f "${PWD}/../../protobuf"` @@ -19,6 +20,13 @@ function stop_server { title_print "Shutdown service server" kill -SIGTERM $(cat build/pidfile) unlink build/pidfile + if [ "${FAIL}" == "1" ]; then + for i in build/output*; do + echo "File: $i" + cat $i + done + find . -name "*.log" -print -exec cat {} \; || true + fi } function test_c { @@ -80,6 +88,8 @@ test_restore_loop test_ps test_errno +FAIL=0 + stop_server trap 'echo "Success"' EXIT From 2b5f91f9803b8e8b641f4f24489fb4fa3bea4283 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 5 Feb 2025 07:51:38 +0000 Subject: [PATCH 6/7] ci: do not run tests requiring iptables if it is missing There are a couple of tests that require the iptables binary. Instead of adding a checkskip script, which could also handle this, this change now uses CRIU's feature detection to see if the CRIU feature 'has_ipt_legacy' exists. Signed-off-by: Adrian Reber --- test/zdtm/static/net_lock_socket_iptables.desc | 1 + test/zdtm/static/net_lock_socket_iptables6.desc | 1 + test/zdtm/static/netns-nf.desc | 1 + test/zdtm/static/netns_lock_iptables.desc | 1 + test/zdtm/static/socket-tcp-closed-last-ack.desc | 2 +- test/zdtm/static/socket-tcp-reseted.desc | 2 +- test/zdtm/static/socket-tcp-syn-sent.desc | 2 +- 7 files changed, 7 insertions(+), 3 deletions(-) diff --git a/test/zdtm/static/net_lock_socket_iptables.desc b/test/zdtm/static/net_lock_socket_iptables.desc index 936ff87027..cb622536f9 100644 --- a/test/zdtm/static/net_lock_socket_iptables.desc +++ b/test/zdtm/static/net_lock_socket_iptables.desc @@ -1,5 +1,6 @@ { 'flavor': 'h', + 'feature': 'has_ipt_legacy', 'flags': 'suid excl reqrst', 'dopts': '--tcp-established --network-lock iptables', 'ropts': '--tcp-established', diff --git a/test/zdtm/static/net_lock_socket_iptables6.desc b/test/zdtm/static/net_lock_socket_iptables6.desc index 936ff87027..cb622536f9 100644 --- a/test/zdtm/static/net_lock_socket_iptables6.desc +++ b/test/zdtm/static/net_lock_socket_iptables6.desc @@ -1,5 +1,6 @@ { 'flavor': 'h', + 'feature': 'has_ipt_legacy', 'flags': 'suid excl reqrst', 'dopts': '--tcp-established --network-lock iptables', 'ropts': '--tcp-established', diff --git a/test/zdtm/static/netns-nf.desc b/test/zdtm/static/netns-nf.desc index c99696d1cf..58c23e8ba8 100644 --- a/test/zdtm/static/netns-nf.desc +++ b/test/zdtm/static/netns-nf.desc @@ -3,4 +3,5 @@ '/lib/xtables/libxt_standard.so|/usr/lib64/xtables/libxt_standard.so|/usr/lib/iptables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so|/usr/lib/riscv64-linux-gnu/xtables/libxt_standard.so', '/usr/bin/diff'], 'flags': 'suid', + 'feature': 'has_ipt_legacy', 'flavor': 'ns uns'} diff --git a/test/zdtm/static/netns_lock_iptables.desc b/test/zdtm/static/netns_lock_iptables.desc index 69020f34ed..b465706b82 100644 --- a/test/zdtm/static/netns_lock_iptables.desc +++ b/test/zdtm/static/netns_lock_iptables.desc @@ -1,6 +1,7 @@ { 'flavor': 'h', 'flags': 'suid excl reqrst', + 'feature': 'has_ipt_legacy', 'opts': '--tcp-established', 'dopts': '--network-lock iptables', 'ropts': '--join-ns net:/var/run/netns/criu-net-lock-test' diff --git a/test/zdtm/static/socket-tcp-closed-last-ack.desc b/test/zdtm/static/socket-tcp-closed-last-ack.desc index 309854fa53..c77d58477d 100644 --- a/test/zdtm/static/socket-tcp-closed-last-ack.desc +++ b/test/zdtm/static/socket-tcp-closed-last-ack.desc @@ -5,6 +5,6 @@ ], 'opts': '--tcp-established', 'flags': 'suid nouser samens', - 'feature' : 'tcp_half_closed', + 'feature' : 'tcp_half_closed has_ipt_legacy', 'flavor': 'ns uns', } diff --git a/test/zdtm/static/socket-tcp-reseted.desc b/test/zdtm/static/socket-tcp-reseted.desc index 4aa48ad874..ff92e9f9f8 100644 --- a/test/zdtm/static/socket-tcp-reseted.desc +++ b/test/zdtm/static/socket-tcp-reseted.desc @@ -6,5 +6,5 @@ ], 'opts': '--tcp-established', 'flags': 'suid nouser samens', - 'feature' : 'tcp_half_closed' + 'feature' : 'tcp_half_closed has_ipt_legacy' } diff --git a/test/zdtm/static/socket-tcp-syn-sent.desc b/test/zdtm/static/socket-tcp-syn-sent.desc index 71cd26d727..52382414bd 100644 --- a/test/zdtm/static/socket-tcp-syn-sent.desc +++ b/test/zdtm/static/socket-tcp-syn-sent.desc @@ -5,5 +5,5 @@ ], 'opts': '--tcp-established', 'flags': 'suid nouser samens', - 'feature' : 'tcp_half_closed' + 'feature' : 'tcp_half_closed has_ipt_legacy' } From b9f478521639d519e1b5d0089b38030e4fd386c1 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 4 Feb 2025 16:10:02 +0000 Subject: [PATCH 7/7] ci: run tests on a nftables only system Signed-off-by: Adrian Reber --- .github/workflows/nftables-test.yml | 24 ++++++++++++++++++++++++ criu/cr-service.c | 3 +++ criu/lsm.c | 2 +- scripts/ci/run-ci-tests.sh | 13 ++++++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/nftables-test.yml diff --git a/.github/workflows/nftables-test.yml b/.github/workflows/nftables-test.yml new file mode 100644 index 0000000000..eb3d8e8141 --- /dev/null +++ b/.github/workflows/nftables-test.yml @@ -0,0 +1,24 @@ +name: Nftables bases testing + +on: [push, pull_request] + +# Cancel any preceding run on the pull request. +concurrency: + group: nftables-test-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/criu-dev' }} + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Remove iptables + run: sudo apt remove -y iptables + - name: Install libnftables-dev + run: sudo scripts/ci/apt-install libnftables-dev + - name: chmod 755 /home/runner + # CRIU's tests are sometimes running as some random user and need + # to be able to access the test files. + run: sudo chmod 755 /home/runner + - name: Build with nftables network locking backend + run: sudo make -C scripts/ci local COMPILE_FLAGS="NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES" diff --git a/criu/cr-service.c b/criu/cr-service.c index b9d11ced22..60adcc7dad 100644 --- a/criu/cr-service.c +++ b/criu/cr-service.c @@ -582,6 +582,7 @@ static int setup_opts_from_req(int sk, CriuOpts *req) goto err; } } + pr_debug("opts.network_lock_method %d\n", opts.network_lock_method); if (req->ps) { opts.port = (short)req->ps->port; @@ -701,6 +702,8 @@ static int setup_opts_from_req(int sk, CriuOpts *req) if (req->lsm_profile) { opts.lsm_supplied = true; SET_CHAR_OPTS(lsm_profile, req->lsm_profile); + pr_debug("opts.lsm_supplied %d\n", opts.lsm_supplied); + pr_debug("lsm_profile %s\n", opts.lsm_profile); } if (req->lsm_mount_context) diff --git a/criu/lsm.c b/criu/lsm.c index d1b73cc79e..70b66d42ee 100644 --- a/criu/lsm.c +++ b/criu/lsm.c @@ -370,7 +370,7 @@ int render_lsm_profile(char *profile, char **val) case LSMTYPE__APPARMOR: return render_aa_profile(val, profile); case LSMTYPE__SELINUX: - if (asprintf(val, "%s", profile) < 0) { + if (asprintf(val, "%s", opts.lsm_supplied ? opts.lsm_profile : profile) < 0) { *val = NULL; return -1; } diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 611ff78037..0c4a089757 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -39,6 +39,10 @@ ci_prep () { # This can fail on aarch64 travis service apport stop || : + # Ubuntu has set up AppArmor in 24.04 so that it blocks use of user + # namespaces by unprivileged users. We need this for some of our tests. + sysctl kernel.apparmor_restrict_unprivileged_userns=0 || : + if [ "$CLANG" = "1" ]; then # clang support CC=clang @@ -121,8 +125,14 @@ if [ "${CD_TO_TOP}" = "1" ]; then fi export GCOV CC +if [ -z "$COMPILE_FLAGS" ]; then + LOCAL_COMPILE_FLAGS=("V=1") +else + IFS=" " read -r -a LOCAL_COMPILE_FLAGS <<< "$COMPILE_FLAGS" + LOCAL_COMPILE_FLAGS=("V=1" "${LOCAL_COMPILE_FLAGS[@]}") +fi $CC --version -time make CC="$CC" -j4 V=1 +time make CC="$CC" -j4 "${LOCAL_COMPILE_FLAGS[@]}" ./criu/criu -v4 cpuinfo dump || : ./criu/criu -v4 cpuinfo check || : @@ -150,6 +160,7 @@ ulimit -c unlimited cgid=$$ cleanup_cgroup() { ./test/zdtm_umount_cgroups $cgid + dmesg } trap cleanup_cgroup EXIT ./test/zdtm_mount_cgroups $cgid