diff options
author | Pavel Tikhomirov <ptikhomirov@virtuozzo.com> | 2020-11-02 15:00:58 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2021-09-03 20:31:00 +0300 |
commit | 371d9c83d7f9294f5a235069e3e472c72b58a017 (patch) | |
tree | db62beb6f7c3fc7400a4ec7e44b749ed611cdcf1 /test/others/ns_ext | |
parent | eb9ed1aafa2209a5fd2624096a7b68937e86bcbb (diff) |
others/ns_ext: restore a process out of PID namespaces into the host PID namespace
It is quiet a common case to move the process from one pidns to another
existing pidns with criu (only restriction is pids should not
intersect). Let's check it works.
v2: - use pipe-s to synchronize processes
- run the test in a pid namespace to avoid pid conflicts in the host
pid namespace
- grep errors in restore.log
- add some more comments
v3: use 1000 for ns_last_pid so that test works on systems with low
pid_max; remove excess ';'s.
Co-Developed-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Diffstat (limited to 'test/others/ns_ext')
-rw-r--r-- | test/others/ns_ext/Makefile | 9 | ||||
-rw-r--r-- | test/others/ns_ext/__run_pidns.sh | 21 | ||||
-rw-r--r-- | test/others/ns_ext/_run_pidns.sh | 33 | ||||
-rwxr-xr-x | test/others/ns_ext/run_pidns.sh | 59 |
4 files changed, 121 insertions, 1 deletions
diff --git a/test/others/ns_ext/Makefile b/test/others/ns_ext/Makefile index f859b89bc..d15224d52 100644 --- a/test/others/ns_ext/Makefile +++ b/test/others/ns_ext/Makefile @@ -1,7 +1,14 @@ -run: +run: run_pidns run_net run_pid + +run_net: ./run.sh net + +run_pid: ./run.sh pid +run_pidns: + unshare -fp -m --mount-proc --propagation private ./run_pidns.sh + clean: rm -rf images output pidfile pidfile2 pidfile3 .PHONY: clean run diff --git a/test/others/ns_ext/__run_pidns.sh b/test/others/ns_ext/__run_pidns.sh new file mode 100644 index 000000000..50cdb6b76 --- /dev/null +++ b/test/others/ns_ext/__run_pidns.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +status_fd=$1 + +exec 0</dev/null +exec 2>/dev/null +exec 1>/dev/null + +# Sending our real pid to run_pidns.sh over pipe + +exec {fd}</proc/self/status +pid=$(cat <&$fd | grep '^Pid:' | awk '{print $2}') +exec {fd}>&- +echo $pid >&$status_fd +exec {status_fd}>&- + +while :; do + sleep 10000 +done diff --git a/test/others/ns_ext/_run_pidns.sh b/test/others/ns_ext/_run_pidns.sh new file mode 100644 index 000000000..b0b266ad6 --- /dev/null +++ b/test/others/ns_ext/_run_pidns.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +status_fd=$1 + +# Note that with this block we only guaranty that pid of +# __run_pidns.sh would be somewhere around 1000, not +# exactly 1000. + +mkdir -p pidns_proc +mount -t proc proc pidns_proc +echo 1000 > pidns_proc/sys/kernel/ns_last_pid +umount -l pidns_proc +rmdir pidns_proc + +# Here we create a pipe to wait for __run_pidns.sh to die, +# when it dies the pipe_w is closed and read from pipe_r +# is unblocked. + +exec {pipe}<> <(:) +exec {pipe_r}</proc/self/fd/$pipe +exec {pipe_w}>/proc/self/fd/$pipe +exec {pipe}>&- + +setsid bash __run_pidns.sh $status_fd & +exec {pipe_w}>&- +exec {status_fd}>&- + +# Waiting for __run_pidns.sh to be checkpointed + +cat <&$pipe_r +echo "Temporary pidns init is exiting..." diff --git a/test/others/ns_ext/run_pidns.sh b/test/others/ns_ext/run_pidns.sh new file mode 100755 index 000000000..b4c7b88a8 --- /dev/null +++ b/test/others/ns_ext/run_pidns.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +set -e + +# This test creates a process in non-host pidns and then dumps it and restores +# it into host pidns. We use pid >100000 in non-host pidns to make sure it does +# not intersect with some host pid on restore but it is potentially racy so +# please run this test only in manualy. + +CRIU=../../../criu/criu + +# This is a status pipe to report the pid of __run_pidns.sh +exec {pipe}<> <(:) +exec {pipe_r}</proc/self/fd/$pipe +exec {pipe_w}>/proc/self/fd/$pipe +exec {pipe}>&- + +unshare -p sh -c "bash _run_pidns.sh $pipe_w &" +exec {pipe_w}>&- + +PID=$(cat <&$pipe_r) +echo PID: $PID + +PIDNS=$(readlink /proc/$PID/ns/pid | sed 's/://') +echo PIDNS: $PIDNS + +BEFORE=$(grep NSpid /proc/$PID/status) +echo "before c/r: $BEFORE" + +rm -rf images_pidns || : +mkdir -p images_pidns + +echo "$CRIU dump -v4 -o dump.log -t $PID -D images_pidns --external $PIDNS:exti" +$CRIU dump -v4 -o dump.log -t $PID -D images_pidns --external $PIDNS:exti +RESULT=$? +cat images_pidns/dump.log | grep -B 5 Error || echo ok +[ "$RESULT" != "0" ] && { + echo "CRIU dump failed" + echo FAIL + exit 1 +} + +exec {pidns_fd}< /proc/self/ns/pid + +echo "$CRIU restore -v4 -o restore.log -D images_pidns --restore-detached --inherit-fd fd[$pidns_fd]:exti" +$CRIU restore -v4 -o restore.log -D images_pidns --restore-detached --inherit-fd fd[$pidns_fd]:exti --pidfile test.pidfile +RESULT=$? +cat images_pidns/restore.log | grep -B 5 Error || echo ok +[ "$RESULT" != "0" ] && { + echo "CRIU restore failed" + echo FAIL + exit 1 +} + +PID=$(cat images_pidns/test.pidfile) +AFTER=$(grep NSpid /proc/$PID/status) +echo "after c/r: $AFTER" +echo PASS +exit 0 |