[CRIU] [PATCH 8/8] zdtm: check that pid-reuse does not break iterative memory dump
Andrew Vagin
avagin at virtuozzo.com
Tue Feb 13 22:57:39 MSK 2018
On Mon, Feb 12, 2018 at 01:31:05PM +0300, Pavel Tikhomirov wrote:
> From: ptikhomirov <ptikhomirov at virtuozzo.com>
>
> The idea of the test is:
>
> 1) mmap separate page and put variable there, so that other usage does
> not dirty these region. Initialize the variable with VALUE_A.
>
> 2) fork a child with special pid == CHILD_NS_PID. Only if it is a first
> child overwrite the variable with VALUE_B.
>
> 3) wait for the end of the next predump or end of restore with
> test_waitpre and kill our child.
>
> Note: The memory region is "clean" in parent.
>
> 4) goto (2) unles end of cr is reported by test_waitpre
>
> So on first iteration child with pid CHILD_NS_PID was dumped with
> VALUE_B, on all other iterations and on final dump other child with the
> same pid exists but with VALUE_A. But on all iterations after the first
> one we have these memory region "clean". So criu before the fix would
> have restored the VALUE_B taking it from first child's image, but should
> restore VALUE_A.
>
> Note: Child in its turn waits termination and performs a check that variable
> value doesn't change after c/r.
>
> We should run the test with at least one predump to trigger the problem:
>
> [root at snorch criu]# ./test/zdtm.py run --pre 1 -k always -t zdtm/transition/pid_reuse
> Checking feature ns_pid
> Checking feature ns_get_userns
> Checking feature ns_get_parent
>
> === Run 1/1 ================ zdtm/transition/pid_reuse
>
> ===================== Run zdtm/transition/pid_reuse in ns ======================
> DEP pid_reuse.d
> CC pid_reuse.o
> LINK pid_reuse
> Start test
> Test is SUID
> ./pid_reuse --pidfile=pid_reuse.pid --outfile=pid_reuse.out
> Run criu pre-dump
> Send the 10 signal to 52
> Run criu dump
> Run criu restore
> Send the 15 signal to 73
> Wait for zdtm/transition/pid_reuse(73) to die for 0.100000
> Test output: ================================
> 14:47:57.717: 11235: ERR: pid_reuse.c:76: Wrong value in a variable after restore
> 14:47:57.717: 4: FAIL: pid_reuse.c:110: Task 11235 exited with wrong code 1 (errno = 11 (Resource temporarily unavailable))
>
> <<< ================================
>
> https://jira.sw.ru/browse/PSBM-67502
>
> Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
> ---
> test/zdtm/transition/Makefile | 1 +
> test/zdtm/transition/pid_reuse.c | 118 ++++++++++++++++++++++++++++++++++++
> test/zdtm/transition/pid_reuse.desc | 1 +
> 3 files changed, 120 insertions(+)
> create mode 100644 test/zdtm/transition/pid_reuse.c
> create mode 100644 test/zdtm/transition/pid_reuse.desc
>
> diff --git a/test/zdtm/transition/Makefile b/test/zdtm/transition/Makefile
> index f482a8a09..35301ac85 100644
> --- a/test/zdtm/transition/Makefile
> +++ b/test/zdtm/transition/Makefile
> @@ -21,6 +21,7 @@ TST_NOFILE = \
> socket-tcp6 \
> shmem \
> lazy-thp \
> + pid_reuse \
>
>
> TST_FILE = \
> diff --git a/test/zdtm/transition/pid_reuse.c b/test/zdtm/transition/pid_reuse.c
> new file mode 100644
> index 000000000..1400bf202
> --- /dev/null
> +++ b/test/zdtm/transition/pid_reuse.c
> @@ -0,0 +1,118 @@
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <stdlib.h>
> +#include <signal.h>
> +#include <sys/wait.h>
> +#include <sys/mman.h>
> +
> +#include "zdtmtst.h"
> +
> +const char *test_doc = "Tests that forking tasks with same pid does not break iterative dump";
> +const char *test_author = "Pavel Tikhomirov <ptikhomirov at virtuozzo.com>";
> +
> +enum {
> + VALUE_A = 1,
> + VALUE_B = 2,
> +};
> +
> +#define CHILD_NS_PID 11235
> +
> +static int set_ns_next_pid(pid_t pid)
> +{
> + char buf[32];
> + int len, fd;
> +
> + fd = open("/proc/sys/kernel/ns_last_pid", O_WRONLY);
> + if (fd < 0) {
> + pr_perror("Failed to open ns_last_pid");
> + return -1;
> + }
> +
> + len = snprintf(buf, sizeof(buf), "%d", pid - 1);
> + len -= write(fd, buf, len);
> + if (len)
> + pr_perror("Can't set ns_last_pid");
> + close(fd);
> +
> + return len ? -1 : 0;
> +}
> +
> +int main(int argc, char **argv)
> +{
> + int pid, wpid, status;
> + bool overwrite = true;
> + bool wait = true;
> + int *variable;
> + void *mem;
> +
> + test_init(argc, argv);
> +
> + mem = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> + if (mem == MAP_FAILED) {
> + pr_perror("Can't mmap memory region");
> + return 1;
> + }
> +
> + variable = (int *)mem;
> + *variable = VALUE_A;
> +
> + test_daemon();
> +
> + while (wait) {
> + if (set_ns_next_pid(CHILD_NS_PID))
> + return 1;
> +
> + pid = fork();
> + if (pid == -1) {
> + pr_perror("fork");
> + return 1;
> + } else if (pid == 0) {
> + if (overwrite)
> + *variable = VALUE_B;
> + test_waitsig();
> +
> + if (*variable != (overwrite ? VALUE_B : VALUE_A)) {
> + pr_err("Wrong value in a variable after restore\n");
> + exit(1);
> + }
> + exit(0);
> + }
> +
> + if (pid != CHILD_NS_PID) {
> + pr_err("Child started with wrong pid %d (expected %d)\n", pid, CHILD_NS_PID);
> + kill(pid, SIGKILL);
> + waitpid(pid, NULL, 0);
> + return 1;
> + }
> +
> + /* Wait for next predump/dump finish */
> + if (test_waitpre())
> + wait = false;
> +
> + if (kill(pid, SIGTERM)) {
> + pr_perror("kill");
> + return 1;
> + }
> +
> + wpid = waitpid(pid, &status, 0);
> + if (wpid <= 0) {
> + pr_perror("waitpid");
> + return 1;
> + }
> +
> + if (!WIFEXITED(status)) {
> + fail("Task %d didn't exit", wpid);
The process can be killed (WIFSIGNALED()).
Pls, don't decode status, it is enough to check whether status is
zero of not.
if (status) {
fail("The task %d exited with %x", wpid, status);
return 1;
}
> + return 1;
> + }
> +
> + if (WEXITSTATUS(status) != 0) {
> + fail("Task %d exited with wrong code %d", wpid, WEXITSTATUS(status));
> + return 1;
> + }
> +
> + overwrite = false;
> + }
> + pass();
> + return 0;
> +}
> diff --git a/test/zdtm/transition/pid_reuse.desc b/test/zdtm/transition/pid_reuse.desc
> new file mode 100644
> index 000000000..1d1a44053
> --- /dev/null
> +++ b/test/zdtm/transition/pid_reuse.desc
> @@ -0,0 +1 @@
> +{'flavor': 'ns uns', 'flags': 'suid', 'feature': 'ns_pid ns_get_userns ns_get_parent'}
> --
> 2.14.3
>
More information about the CRIU
mailing list