[Libct] ***SPAM*** Re: [PATCH v2 3/6] VZ containers: implemented spawn_execve

Andrew Vagin avagin at gmail.com
Wed Nov 12 14:00:56 PST 2014


On Wed, Nov 12, 2014 at 03:52:17PM +0300, Alexander Burluka wrote:
> +static int vz_env_create(ct_handler_t h, struct info_pipes *pipes, struct execv_args *ea)
> +{
> +	int ret, pid, n;
> +	struct container *ct = cth2ct(h);
> +	unsigned int veid;
> +
> +	if (parse_uint(ct->name, &veid) < 0) {
> +		pr_err("Unable to parse container's ID");
> +		return -1;
> +	}
> +
> +	if (!ct->root_path) {
> +		pr_err("Root path is not set");
> +		return -1;
> +	}
> +	if ((ret = vzctl_chroot(ct->root_path)))
> +		goto err;
> +	if ((ret = syscall(__NR_setluid, veid)))
> +		goto err;
> +
> +	/* Create another process for proper resource accounting */
> +	if ((pid = fork()) < 0) {
> +		pr_perror("Can not fork");
> +		ret = -1;
> +		goto err;
> +	} else if (pid == 0) {
> +		ret = env_create(h, pipes, ea);
> +
> +		n = write(pipes->parent_wait[1], &ret, sizeof(ret));
> +		_exit(ret);

The local driver doesn't detach from containers. Can we do the same
here?

> +	}
> +	if (write(pipes->parent_wait[1], &pid, sizeof(pid)) == -1) {
> +		pr_perror("Unable to write to parent_wait pipe");
> +		goto err;
> +	}
> +
> +	if (env_wait(pid, 0, NULL)) {
> +		pr_perror("Execution failed");
> +		goto err;
> +	}
> +	return 0;
> +
> +err:
> +	if (write(pipes->parent_wait[1], &ret, sizeof(ret)) == -1)
> +		pr_perror("Failed write() pipes->parent_wait[1] vz_env_create");
> +	return ret;
> +}
> +
>  static int vz_spawn_cb(ct_handler_t h, ct_process_desc_t p, int (*cb)(void *), void *arg)
>  {
>  	pr_err("Spawn with callback is not supported");
>  	return -1;
>  }
>  
> +static int vz_spawn_execve(ct_handler_t h, ct_process_desc_t p, char *path, char **argv, char **env, int *fds)
> +{
> +	int ret = -1;
> +	int child_wait[2];
> +	int parent_wait[2];
> +	struct container *ct = cth2ct(h);
> +	struct execv_args ea = {
> +		.path = path,
> +		.argv = argv,
> +		.env = env,
> +		.fds = fds
> +	};
> +	struct info_pipes pipes = {
> +		.child_wait = child_wait,
> +		.parent_wait = parent_wait,
> +	};
> +	struct sigaction act;
> +	int pid = -1;
> +	int root_pid = -1;
> +
> +	if (ct->state != CT_STOPPED) {
> +		ret = -LCTERR_BADCTSTATE;
> +		goto err;
> +	}
> +
> +	ret = pipe(child_wait);
> +	if (ret == -1) {
> +		pr_perror("Cannot create child wait pipe");
> +		goto err;
> +	}
> +	ret = pipe(parent_wait);
> +	if (ret == -1) {
> +		pr_perror("Cannot create parent wait pipe");
> +		goto err_pipe;
> +	}
> +
> +	ret = fs_mount(ct);
> +	if (ret) {
> +		pr_err("Unable to mount fs");
> +		goto err_pipe;
> +	}
> +
> +	sigemptyset(&act.sa_mask);
> +	act.sa_handler = SIG_IGN;
> +	act.sa_flags = SA_NOCLDSTOP;
> +	sigaction(SIGPIPE, &act, NULL);
> +	if ((pid = fork()) < 0) {
> +		pr_perror("Cannot fork");
> +		ret = -1;
> +		goto err_fork;
> +	} else if (pid == 0) {
> +		sigaction(SIGCHLD, &act, NULL);
> +
> +		fcntl(parent_wait[1], F_SETFD, FD_CLOEXEC);
> +		close(parent_wait[0]);
> +		fcntl(child_wait[0], F_SETFD, FD_CLOEXEC);
> +		close(child_wait[1]);
> +
> +		ret = vz_env_create(h, &pipes, &ea);
> +
> +		_exit(ret);
> +	}
> +	close(parent_wait[1]);
> +	parent_wait[1] = -1;
> +	close(child_wait[0]);
> +	child_wait[0] = -1;
> +
> +	if (read(parent_wait[0], &root_pid, sizeof(root_pid)) == -1) {
> +		pr_perror("Unable to read parent_wait pipe");
> +		ret = -1;
> +		goto err_wait;
> +	}
> +	ct->root_pid = root_pid;
> +
> +	if (proc_wait(parent_wait) == -1) {
> +		ret = -1;
> +		goto err_net;
> +	}
> +
> +	proc_wake(child_wait, 0);
> +
> +	/* Wait while network would be configured inside container */
> +	if (proc_wait_close(parent_wait)) {
> +		ret = -1;
> +		goto err_wait;
> +	}
> +	proc_wake_close(child_wait, 0);
> +
> +	ct->state = CT_RUNNING;
> +	return ct->root_pid;
> +
> +err_wait:
> +err_net:
> +	proc_wake_close(child_wait, -1);
> +err_fork:
> +	fs_umount(ct);
> +	close(parent_wait[0]);
> +	close(parent_wait[1]);
> +err_pipe:
> +	close(child_wait[0]);
> +	close(child_wait[1]);
> +err:
> +	return ret;
> +}
> +
>  static int vz_set_option(ct_handler_t h, int opt, void *args)
>  {
>  	int ret = -LCTERR_BADTYPE;
> @@ -662,7 +1050,7 @@ static int vz_config_controller(ct_handler_t h, enum ct_controller ctype,
>  
>  static const struct container_ops vz_ct_ops = {
>  	.spawn_cb		= vz_spawn_cb,
> -	.spawn_execve		= NULL,
> +	.spawn_execve		= vz_spawn_execve,
>  	.enter_cb		= NULL,
>  	.enter_execve		= NULL,
>  	.kill			= vz_ct_kill,
> diff --git a/test/Makefile b/test/Makefile
> index 89b1547..ac477da 100644
> --- a/test/Makefile
> +++ b/test/Makefile
> @@ -3,18 +3,23 @@ TESTS =	ct_create ct_enter ct_proc ct_root ct_root_enter \
>  	ct_net_veth ct_private_subdir \
>  	ct_ext_mount ct_private_subdir_ns \
>  	ct_cgroup_sub ct_service ct_kill_nons ct_pid_enter \
> -	ct_userns ct_caps
> +	ct_userns ct_caps \
> +	vz_create_exec

Have you checked that all this work with the local driver?

>  


More information about the Libct mailing list