[CRIU] [PATCH 07/11] vdso/zdtm: Add iterative proxification test

Dmitry Safonov dsafonov at virtuozzo.com
Mon Jul 17 15:39:58 MSK 2017


Test for previously fixed bugs for vdso-trampolines insertion:
- unmapping original vvar (which went unnoticed)
- leaving rt-vvar after each C/R cycle and resulting pollution

Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
 test/jenkins/criu-fault.sh    |   1 +
 test/zdtm/static/Makefile     |   1 +
 test/zdtm/static/vdso-proxy.c | 147 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 test/zdtm/static/vdso-proxy.c

diff --git a/test/jenkins/criu-fault.sh b/test/jenkins/criu-fault.sh
index b7879116dc29..1e9862f7de1e 100755
--- a/test/jenkins/criu-fault.sh
+++ b/test/jenkins/criu-fault.sh
@@ -10,6 +10,7 @@ prep
 ./test/zdtm.py run -t zdtm/static/env00 --fault 129 -f uns || fail
 ./test/zdtm.py run -t zdtm/transition/fork --fault 130 -f h || fail
 ./test/zdtm.py run -t zdtm/static/vdso01 --fault 127 || fail
+./test/zdtm.py run -t zdtm/static/vdso-proxy --fault 127 --iters 3 || fail
 
 ./test/zdtm.py run -t zdtm/static/mntns_ghost --fault 2 --keep-going --report report || fail
 ./test/zdtm.py run -t zdtm/static/mntns_ghost --fault 4 --keep-going --report report || fail
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 6947e055b0c6..8d5f4d532fd2 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -55,6 +55,7 @@ TST_NOFILE	:=				\
 		vdso00				\
 		vdso01				\
 		vdso02				\
+		vdso-proxy			\
 		utsname				\
 		pstree				\
 		sockets01			\
diff --git a/test/zdtm/static/vdso-proxy.c b/test/zdtm/static/vdso-proxy.c
new file mode 100644
index 000000000000..eadd9af8b0fd
--- /dev/null
+++ b/test/zdtm/static/vdso-proxy.c
@@ -0,0 +1,147 @@
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc	= "Compare mappings before/after C/R for vdso/vvar presence. Should run iterative under vdso proxy fault-injection.\n";
+const char *test_author	= "Dmitry Safonov <dsafonov at virtuozzo.com>";
+
+#define BUILD_BUG_ON(condition)	((void)sizeof(char[1 - 2*!!(condition)]))
+#define VDSO_BAD_ADDR		(-1ul)
+#define MAX_VMAS		80
+#define BUF_SIZE		1024
+
+/*
+ * After C/R with vdso trampolines insertion, there should
+ * be added one or two vmas: vdso and possibly vvar.
+ * We need to check that nr. vmas after C/R <= +2 new vmas.
+ * Also previous vdso/vvar vma should still be present after C/R.
+ */
+struct vm_area {
+	unsigned long start;
+	unsigned long end;
+	bool is_vvar_or_vdso;
+};
+
+static char buf[BUF_SIZE];
+
+static int parse_maps(struct vm_area *vmas)
+{
+	FILE *maps;
+	int i;
+
+	maps = fopen("/proc/self/maps", "r");
+	if (maps == NULL) {
+		pr_err("Failed to open maps file: %m\n");
+		return -1;
+	}
+
+	for (i = 0; i < MAX_VMAS; i++) {
+		struct vm_area *v = &vmas[i];
+		char *end;
+
+		if (fgets(buf, BUF_SIZE, maps) == NULL)
+			break;
+
+		v->start = strtoul(buf, &end, 16);
+		v->end = strtoul(end + 1, NULL, 16);
+		v->is_vvar_or_vdso |= strstr(buf, "[vdso]") != NULL;
+		v->is_vvar_or_vdso |= strstr(buf, "[vvar]") != NULL;
+		test_msg("[NOTE]\tVMA: [%#lx, %#lx]\n", v->start, v->end);
+	}
+
+	if (i == MAX_VMAS) {
+		pr_err("Number of VMAs is bigger than reserved array's size\n");
+		return -1;
+	}
+
+	if (fclose(maps)) {
+		pr_err("Failed to close maps file: %m\n");
+		return -1;
+	}
+
+	return i;
+}
+
+int compare_vmas(struct vm_area *vmax, struct vm_area *vmay)
+{
+	if (vmax->start > vmay->start)
+		return 1;
+	if (vmax->start < vmay->start)
+		return -1;
+	if (vmax->end > vmay->end)
+		return 1;
+	if (vmax->end < vmay->end)
+		return -1;
+
+	return 0;
+}
+
+static int check_vvar_vdso(struct vm_area *before, struct vm_area *after)
+{
+	int i, j = 0;
+
+	for (i = 0; i < MAX_VMAS && j < MAX_VMAS; i++, j++) {
+		int cmp = compare_vmas(&before[i], &after[j]);
+
+		if (cmp == 0)
+			continue;
+
+		if (cmp < 0) {/* Lost mapping */
+			test_msg("[NOTE]\tLost mapping: %#lx-%#lx\n",
+				before[i].start, before[i].end);
+			j--;
+			if (before[i].is_vvar_or_vdso) {
+				fail("Lost vvar/vdso mapping");
+				return -1;
+			}
+			continue;
+		}
+
+		test_msg("[NOTE]\tNew mapping appeared: %#lx-%#lx\n",
+			after[j].start, after[j].end);
+		i--;
+	}
+
+	return 0;
+}
+
+static struct vm_area vmas_before[MAX_VMAS];
+static struct vm_area vmas_after[MAX_VMAS];
+
+int main(int argc, char *argv[])
+{
+	int nr_before, nr_after;
+
+	test_init(argc, argv);
+
+	test_msg("[NOTE]\tMappings before:\n");
+	nr_before = parse_maps(vmas_before);
+	if (nr_before < 0) {
+		pr_perror("Faied to parse maps");
+		return -1;
+	}
+
+	test_daemon();
+	test_waitsig();
+
+	test_msg("[NOTE]\tMappings after:\n");
+	nr_after = parse_maps(vmas_after);
+	if (nr_after < 0) {
+		pr_perror("Faied to parse maps");
+		return -1;
+	}
+
+	/* After restore vDSO/VVAR blobs must remain in the old place. */
+	if (check_vvar_vdso(vmas_before, vmas_after))
+		return -1;
+
+	if (nr_before + 2 < nr_after) {
+		fail("There is more than two (VVAR/vDSO) vmas added after C/R");
+		return -1;
+	}
+
+	pass();
+
+	return 0;
+}
-- 
2.13.1



More information about the CRIU mailing list