[CRIU] [RFC 4/4] tests: add a cgroupns test

Tycho Andersen tycho.andersen at canonical.com
Thu Feb 11 09:37:35 PST 2016


Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 test/zdtm/.gitignore                |   1 +
 test/zdtm/live/static/Makefile      |   1 +
 test/zdtm/live/static/cgroupns.c    | 235 ++++++++++++++++++++++++++++++++++++
 test/zdtm/live/static/cgroupns.desc |   1 +
 4 files changed, 238 insertions(+)
 create mode 100644 test/zdtm/live/static/cgroupns.c
 create mode 100644 test/zdtm/live/static/cgroupns.desc

diff --git a/test/zdtm/.gitignore b/test/zdtm/.gitignore
index 3e6c7e2..1892f45 100644
--- a/test/zdtm/.gitignore
+++ b/test/zdtm/.gitignore
@@ -9,6 +9,7 @@
 /live/static/cgroup01
 /live/static/cgroup02
 /live/static/cgroup03
+/live/static/cgroupns
 /live/static/child_opened_proc
 /live/static/chroot
 /live/static/chroot-file
diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index d3ff2c0..2c87db6 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -216,6 +216,7 @@ TST_DIR		=				\
 		cgroup01			\
 		cgroup02			\
 		cgroup03			\
+		cgroupns			\
 		mntns_open			\
 		mntns_link_remap		\
 		mntns_link_ghost		\
diff --git a/test/zdtm/live/static/cgroupns.c b/test/zdtm/live/static/cgroupns.c
new file mode 100644
index 0000000..e2101bd
--- /dev/null
+++ b/test/zdtm/live/static/cgroupns.c
@@ -0,0 +1,235 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <limits.h>
+#include "zdtmtst.h"
+
+#ifndef CLONE_NEWCGROUP
+#define CLONE_NEWCGROUP		0x02000000
+#endif
+
+const char *test_doc	= "Check that cgroup NS is correctly handled.";
+const char *test_author	= "Tycho Andersen <tycho.andersen at canonical.com>";
+
+char *dirname;
+TEST_OPTION(dirname, string, "cgroup directory name", 1);
+static const char *cgname = "zdtmtst";
+
+int mount_and_add(const char *controller, const char *path)
+{
+	char aux[1024], paux[1024], subdir[1024];
+	int cgfd, l;
+
+	if (mkdir(dirname, 0700) < 0 && errno != EEXIST) {
+		pr_perror("Can't make dir");
+		return -1;
+	}
+
+	sprintf(subdir, "%s/%s", dirname, controller);
+	if (mkdir(subdir, 0700) < 0) {
+		pr_perror("Can't make dir");
+		return -1;
+	}
+
+	sprintf(aux, "none,name=%s", controller);
+	if (mount("none", subdir, "cgroup", 0, aux)) {
+		pr_perror("Can't mount cgroups");
+		goto err_rd;
+	}
+
+	sprintf(paux, "%s/%s", subdir, path);
+	mkdir(paux, 0600);
+
+	l = sprintf(aux, "%d", getpid());
+	sprintf(paux, "%s/%s/tasks", subdir, path);
+
+	cgfd = open(paux, O_WRONLY);
+	if (cgfd < 0) {
+		pr_perror("Can't open tasks");
+		goto err_rs;
+	}
+
+	l = write(cgfd, aux, l);
+	close(cgfd);
+
+	if (l < 0) {
+		pr_perror("Can't move self to subcg");
+		goto err_rs;
+	}
+
+	return 0;
+err_rs:
+	umount(dirname);
+err_rd:
+	rmdir(dirname);
+	return -1;
+}
+
+static bool pid_in_cgroup(pid_t pid, const char *controller, const char *path) {
+	char buf[2048];
+	FILE *f;
+	bool ret = false;
+
+	sprintf(buf, "/proc/%d/cgroup", pid);
+	f = fopen(buf, "r");
+	if (!f) {
+		pr_perror("fopen");
+		return false;
+	}
+
+	while (NULL != fgets(buf, sizeof(buf), f)) {
+		char *pos, *pid_controller, *pid_path;
+
+		/* chop off trailing \n */
+		buf[strlen(buf)-1] = '\0';
+
+		/* skip heirarchy no. */
+		pos = strstr(buf, ":");
+		if (!pos) {
+			pr_err("invalid /proc/pid/cgroups file");
+			goto out;
+		}
+		pos++;
+		pid_controller = pos;
+
+		pos = strstr(pos, ":");
+		if (!pos) {
+			pr_err("invalid /proc/pid/cgroups file");
+			goto out;
+		}
+
+		*pos = '\0';
+		pos++;
+		pid_path = pos;
+
+		if (!strcmp(controller, pid_controller))
+			continue;
+
+		if (strcmp(path, pid_path))
+			pr_err("task not in right cg for controller %s expected %s, got %s\n", controller, path, pid_path);
+		else
+			ret = true;
+
+		goto out;
+	}
+
+out:
+	fclose(f);
+	return ret;
+}
+
+static int unshare_cgns_and_wait(void *arg)
+{
+	int sk = *((int*)arg), ret = -1;
+	char c;
+
+	if (unshare(CLONE_NEWCGROUP) < 0) {
+		pr_perror("unshare");
+		goto out;
+	}
+
+	if (write(sk, &c, 1) != 1) {
+		pr_perror("write");
+		goto out;
+	}
+
+
+	if (read(sk, &c, 1) != 1) {
+		pr_perror("read %d", ret);
+		goto out;
+	}
+
+	if (!pid_in_cgroup(getpid(), cgname, "/")) {
+		pr_err("subtask not in right cg!\n");
+		goto out;
+	}
+
+	ret = 0;
+out:
+	close(sk);
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	int ret = -1, sk_pair[2], sk, status;
+	char path[PATH_MAX], c;
+	pid_t pid;
+
+	test_init(argc, argv);
+
+	if (mount_and_add(cgname, "test") < 0)
+		return -1;
+
+	if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair)) {
+		pr_perror("socketpair");
+		goto out;
+	}
+
+	pid = fork();
+	if (pid < 0) {
+		pr_perror("fork failed");
+		goto out;
+	}
+
+	if (pid == 0) {
+		close(sk_pair[0]);
+		if (unshare_cgns_and_wait(sk_pair+1))
+			exit(1);
+		exit(0);
+	}
+
+	close(sk_pair[1]);
+	sk = sk_pair[0];
+
+	if ((ret = read(sk, &c, 1)) != 1) {
+		pr_perror("read %d", ret);
+		goto out;
+	}
+
+	test_daemon();
+	test_waitsig();
+
+	/* first check that the task is in zdtmtst:/test */
+	if (pid_in_cgroup(pid, cgname, "/test")) {
+		fail("pid not in cgroup /test");
+		goto out;
+	}
+
+	/* now have the task check that it is in / */
+	if (write(sk, &c, 1) != 1) {
+		pr_perror("write");
+		goto out;
+	}
+
+	if (pid != waitpid(pid, &status, 0)) {
+		pr_perror("waitpid");
+		goto out;
+	}
+
+	if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+		fail("exit status %s\n", status);
+		goto out;
+	}
+
+	pass();
+	ret = 0;
+out:
+	sprintf(path, "%s/%s/test", dirname, cgname);
+	rmdir(path);
+	sprintf(path, "%s/%s", dirname, cgname);
+	umount(path);
+	rmdir(path);
+	rmdir(dirname);
+	return ret;
+}
diff --git a/test/zdtm/live/static/cgroupns.desc b/test/zdtm/live/static/cgroupns.desc
new file mode 100644
index 0000000..9229924
--- /dev/null
+++ b/test/zdtm/live/static/cgroupns.desc
@@ -0,0 +1 @@
+{'flags': 'suid', 'feature': 'cgroupns'}
-- 
2.6.4



More information about the CRIU mailing list