[Libct] [PATCH 6/7] VZ containers: added enter_execve
Alexander Burluka
aburluka at parallels.com
Wed Nov 12 04:40:27 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