From b68cbdff345fc196e8619164ebf40f1ebaeb6561 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 25 Mar 2025 18:55:39 +0000 Subject: [PATCH] criu: Add time namespace to container config after checkpoint/restore Since v3.14, CRIU always restores processes into a time namespace to prevent backward jumps of monotonic and boottime clocks. This change updates the container configuration to ensure that `runc exec` launches new processes within the container's time namespace. Fixes #2610 Signed-off-by: Andrei Vagin --- libcontainer/criu_linux.go | 7 +++++++ tests/integration/checkpoint.bats | 35 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/libcontainer/criu_linux.go b/libcontainer/criu_linux.go index 468c5ba9f..59befe451 100644 --- a/libcontainer/criu_linux.go +++ b/libcontainer/criu_linux.go @@ -1151,6 +1151,13 @@ func (c *Container) criuNotifications(resp *criurpc.CriuResp, process *Process, } // create a timestamp indicating when the restored checkpoint was started c.created = time.Now().UTC() + if !c.config.Namespaces.Contains(configs.NEWTIME) && + configs.IsNamespaceSupported(configs.NEWTIME) && + c.checkCriuVersion(31400) == nil { + // CRIU restores processes into a time namespace. + c.config.Namespaces = append(c.config.Namespaces, + configs.Namespace{Type: configs.NEWTIME}) + } if _, err := c.updateState(r); err != nil { return err } diff --git a/tests/integration/checkpoint.bats b/tests/integration/checkpoint.bats index 9b8acedf3..3db340613 100644 --- a/tests/integration/checkpoint.bats +++ b/tests/integration/checkpoint.bats @@ -441,3 +441,38 @@ function simple_cr() { pid=$(cat "pid") grep -q "${REL_CGROUPS_PATH}$" "/proc/$pid/cgroup" } + +@test "checkpoint/restore and exec" { + runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox + [ "$status" -eq 0 ] + + testcontainer test_busybox running + + local execed_pid="" + for _ in $(seq 2); do + # checkpoint the running container + runc checkpoint --work-path ./work-dir test_busybox + [ "$status" -eq 0 ] + + # after checkpoint busybox is no longer running + testcontainer test_busybox checkpointed + + # restore from checkpoint + runc restore -d --work-path ./work-dir --console-socket "$CONSOLE_SOCKET" test_busybox + [ "$status" -eq 0 ] + + # busybox should be back up and running + testcontainer test_busybox running + + # verify that previously exec'd process is restored. + if [ -n "$execed_pid" ]; then + runc exec test_busybox ls -ld "/proc/$execed_pid" + [ "$status" -eq 0 ] + fi + + # exec a new background process. + runc exec test_busybox sh -c 'sleep 1000 < /dev/null &> /dev/null & echo $!' + [ "$status" -eq 0 ] + execed_pid=$output + done +}