[Libct] [PATCH v2 5/6] VZ containers: added enter_execve

Alexander Burluka aburluka at parallels.com
Wed Nov 12 04:52:19 PST 2014


Implementation + test
---
 src/vz.c        |  106 ++++++++++++++++++++++++++++++++++++++++++++++---------
 test/Makefile   |    2 +-
 test/vz_enter.c |   45 +++++++++++++++++++++++
 3 files changed, 135 insertions(+), 18 deletions(-)
 create mode 100644 test/vz_enter.c

diff --git a/src/vz.c b/src/vz.c
index ea0d0a7..39f788c 100644
--- a/src/vz.c
+++ b/src/vz.c
@@ -513,9 +513,8 @@ int env_create_data_ioctl(struct vzctl_env_create_data *data)
 	return errcode;
 }
 
-static int exec_init(struct info_pipes *pipes, struct execv_args *ea)
+static int exec_init(struct execv_args *ea)
 {
-	int fd = -1;
 	if (ea == NULL)
 		return -LCTERR_BADARG;
 
@@ -525,14 +524,6 @@ static int exec_init(struct info_pipes *pipes, struct execv_args *ea)
 		dup2(ea->fds[0], STDIN_FILENO);
 		dup2(ea->fds[1], STDOUT_FILENO);
 		dup2(ea->fds[2], STDERR_FILENO);
-	} else {
-		if ((fd = open("/dev/null", O_RDWR)) == -1) {
-			pr_perror("Unable to open /dev/null");
-			return -1;
-		}
-		dup2(fd, STDIN_FILENO);
-		dup2(fd, STDOUT_FILENO);
-		dup2(fd, STDERR_FILENO);
 	}
 
 	execve(ea->path, ea->argv, ea->env);
@@ -600,7 +591,7 @@ try:
 	if ((ret = pre_setup_env(h, pipes)))
 		return ret;
 
-	return exec_init(pipes, ea);
+	return exec_init(ea);
 }
 
 static int vz_env_create(ct_handler_t h, struct info_pipes *pipes, struct execv_args *ea)
@@ -615,7 +606,7 @@ static int vz_env_create(ct_handler_t h, struct info_pipes *pipes, struct execv_
 	}
 
 	if (!ct->root_path) {
-		pr_err("Root path is not set");
+		pr_err("Container %s root_path is empty!", ct->name);
 		return -1;
 	}
 	if ((ret = vzctl_chroot(ct->root_path)))
@@ -623,8 +614,8 @@ static int vz_env_create(ct_handler_t h, struct info_pipes *pipes, struct execv_
 	if ((ret = syscall(__NR_setluid, veid)))
 		goto err;
 
-	/* Create another process for proper resource accounting */
-	if ((pid = fork()) < 0) {
+	pid = fork();
+	if (pid < 0) {
 		pr_perror("Can not fork");
 		ret = -1;
 		goto err;
@@ -910,7 +901,8 @@ static int vz_ct_wait(ct_handler_t h)
 	if (ct->state != CT_RUNNING)
 		return -LCTERR_BADCTSTATE;
 
-	if ((child_pid = fork()) < 0) {
+	child_pid = fork();
+	if (child_pid < 0) {
 		pr_perror("Unable to stop Container, fork failed");
 		goto kill_force;
 	} else if (child_pid == 0) {
@@ -1057,11 +1049,91 @@ static int vz_config_controller(ct_handler_t h, enum ct_controller ctype,
 	return -LCTERR_CGCONFIG;
 }
 
+static int vz_enter_execve(ct_handler_t h, ct_process_desc_t p, char *path, char **argv, char **env, int *fds)
+	struct container *ct = NULL;
+	unsigned int veid = -1;
+	int pid, child_pid, ret = 0;
+	struct execv_args ea = {
+		.path = path,
+		.argv = argv,
+		.env = env,
+		.fds = fds
+	};
+
+	if (!h)
+		return -LCTERR_BADARG;
+
+	ct = cth2ct(h);
+
+	if (ct->state != CT_RUNNING)
+		return -LCTERR_BADCTSTATE;
+
+	if (parse_uint(ct->name, &veid) < 0) {
+		pr_err("Unable to parse container's ID");
+		return -1;
+	}
+
+	pid = fork();
+	if (pid < 0) {
+		pr_perror("Cannot fork");
+		return -1;
+	} else if (pid == 0) {
+		int i;
+		int fd_flags[2];
+
+		for (i = 0; i < 2; i++) {
+			fd_flags[i] = fcntl(i, F_GETFL);
+			if (fd_flags[i] < 0) {
+				pr_perror("Unable to get fd%d flags", i);
+				_exit(-1);
+			}
+		}
+
+		ret = syscall(__NR_setluid, veid);
+		if (ret) {
+			pr_perror("Unable to setluid for container %ld", veid);
+			_exit(ret);
+		}
+
+		ret = vzctl_chroot(ct->root_path);
+		if (ret)
+			_exit(ret);
+
+		pr_info("Entering the Container %ld", veid);
+		child_pid = fork();
+		if (child_pid < 0) {
+			pr_perror("Unable to stop Container, fork failed");
+			_exit(1);
+		} else if (child_pid == 0) {
+			ret = vzctl_env_create_ioctl(veid, VE_ENTER);
+			if (ret >= 0) {
+				execve(ea.path, ea.argv, ea.env);
+			}
+		}
+
+		if (env_wait(child_pid, 0, NULL)) {
+			pr_err("Execution failed");
+			ret = -1;
+			return -1;
+		}
+
+		_exit(0);
+	}
+
+	return pid;
+}
+
+static int vz_enter_cb(ct_handler_t h, ct_process_desc_t p, int (*cb)(void *), void *arg)
+{
+	pr_err("Enter with callback is not supported");
+	return -1;
+}
+
 static const struct container_ops vz_ct_ops = {
 	.spawn_cb		= vz_spawn_cb,
 	.spawn_execve		= vz_spawn_execve,
-	.enter_cb		= NULL,
-	.enter_execve		= NULL,
+	.enter_cb		= vz_enter_cb,
+	.enter_execve		= vz_enter_execve,
 	.kill			= vz_ct_kill,
 	.wait			= vz_ct_wait,
 	.destroy		= vz_ct_destroy,
diff --git a/test/Makefile b/test/Makefile
index 2b879d7..4d07094 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -4,7 +4,7 @@ TESTS =	ct_create ct_enter ct_proc ct_root ct_root_enter \
 	ct_ext_mount ct_private_subdir_ns \
 	ct_cgroup_sub ct_service ct_kill_nons ct_pid_enter \
 	ct_userns ct_caps \
-	vz_create_exec vz_net_veth
+	vz_create_exec vz_net_veth vz_enter
 
 PIGS  = file_piggy
 
diff --git a/test/vz_enter.c b/test/vz_enter.c
new file mode 100644
index 0000000..3b391ac
--- /dev/null
+++ b/test/vz_enter.c
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <libct.h>
+#include <unistd.h>
+#include <sched.h>
+
+#include "test.h"
+
+#define FS_ROOT		"/"
+int main(int argc, char *argv[])
+{
+	libct_session_t s;
+	ct_handler_t ct;
+	ct_process_desc_t p;
+	char *sleep_a[] = { "sleep", "60", NULL};
+	char *ls_a[] = { "ls", "/root/work/libct/test", NULL};
+	int fds[] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO};
+
+	s = libct_session_open_local();
+	ct = libct_container_create(s, "1339");
+	p = libct_process_desc_create(s);
+	libct_fs_set_root(ct, FS_ROOT);
+
+	libct_container_set_nsmask(ct,
+			CLONE_NEWNS |
+			CLONE_NEWUTS |
+			CLONE_NEWIPC |
+			CLONE_NEWNET |
+			CLONE_NEWPID);
+
+	if (libct_container_spawn_execvfds(ct, p, "/bin/sleep", sleep_a, fds) <= 0)
+		goto err;
+
+	if (libct_container_enter_execvfds(ct, p, "/bin/ls", ls_a, fds) <= 0)
+		goto err;
+
+	libct_container_wait(ct);
+	libct_container_destroy(ct);
+
+	libct_session_close(s);
+
+	return pass("All is ok");;
+err:
+	return fail("Something wrong");
+}
-- 
1.7.1



More information about the Libct mailing list