Пример #1
0
static int parasite_init(struct parasite_ctl *ctl, pid_t pid, int nr_threads)
{
	struct parasite_init_args *args;
	static int sock = -1;

	args = parasite_args(ctl, struct parasite_init_args);

	pr_info("Putting tsock into pid %d\n", pid);
	args->h_addr_len = gen_parasite_saddr(&args->h_addr, getpid());
	args->p_addr_len = gen_parasite_saddr(&args->p_addr, pid);
	args->nr_threads = nr_threads;

	if (sock == -1) {
		int rst = -1;

		if (current_ns_mask & CLONE_NEWNET) {
			pr_info("Switching to %d's net for tsock creation\n", pid);

			if (switch_ns(pid, &net_ns_desc, &rst))
				return -1;
		}

		sock = socket(PF_UNIX, SOCK_DGRAM, 0);
		if (sock < 0)
			pr_perror("Can't create socket");

		if (rst > 0 && restore_ns(rst, &net_ns_desc) < 0)
			return -1;
		if (sock < 0)
			return -1;

		if (bind(sock, (struct sockaddr *)&args->h_addr, args->h_addr_len) < 0) {
			pr_perror("Can't bind socket");
			goto err;
		}

	} else {
		struct sockaddr addr = { .sa_family = AF_UNSPEC, };

		/*
		 * When the peer of a dgram socket dies the original socket
		 * remains in connected state, thus denying any connections
		 * from "other" sources. Unconnect the socket by hands thus
		 * allowing for parasite to connect back.
		 */

		if (connect(sock, &addr, sizeof(addr)) < 0) {
			pr_perror("Can't unconnect");
			goto err;
		}
	}

	if (parasite_execute(PARASITE_CMD_INIT, ctl) < 0) {
		pr_err("Can't init parasite\n");
		goto err;
	}

	if (connect(sock, (struct sockaddr *)&args->p_addr, args->p_addr_len) < 0) {
		pr_perror("Can't connect a transport socket");
		goto err;
	}

	ctl->tsock = sock;
	return 0;
err:
	close_safe(&sock);
	return -1;
}
Пример #2
0
Файл: ct.c Проект: mkatkar/libct
static ct_process_t __local_enter_cb(ct_handler_t h, ct_process_desc_t ph, int (*cb)(void *), void *arg, bool is_exec)
{
	struct container *ct = cth2ct(h);
	struct process_desc *p = prh2pr(ph);
	struct process *pr;
	int aux = -1, pid;
	int wait_pipe[2];

	if (ct->state != CT_RUNNING)
		return ERR_PTR(-LCTERR_BADCTSTATE);

	if (ct->nsmask & CLONE_NEWPID) {
		if (switch_ns(ct->p.pid, &pid_ns, &aux))
			return ERR_PTR(-LCTERR_INVARG);
	}

	pr = xmalloc(sizeof(struct process));
	if (pr == NULL)
		return ERR_PTR(-1);

	local_process_init(pr);

	if (pipe(wait_pipe)) {
		xfree(pr);
		return ERR_PTR(-1);
	}

	pid = fork();
	if (pid == 0) {
		struct ns_desc *ns;

		close(wait_pipe[0]);

		if (p->fds) {
			p->fds[p->fdn] = wait_pipe[1];

			if (setup_fds(p->fds, p->fdn + 1))
				exit(-1);

			wait_pipe[1] = p->fdn;
		}

		for (aux = 0; namespaces[aux]; aux++) {
			ns = namespaces[aux];

			if (ns->cflag == CLONE_NEWPID)
				continue;
			if (!(ns->cflag & ct->nsmask))
				continue;

			if (switch_ns(ct->p.pid, ns, NULL))
				exit(-1);
		}

		if (cgroups_attach(ct))
			exit(-1);

		if (ct->root_path && !(ct->nsmask & CLONE_NEWNS)) {
			char nroot[128];

			/*
			 * Otherwise switched by setns()
			 */

			snprintf(nroot, sizeof(nroot), "/proc/%d/root", ct->p.pid);
			if (set_current_root(nroot))
				exit(-1);
		}

		if (apply_creds(p))
			exit(-1);

		if (is_exec)
			spawn_wake_and_cloexec(wait_pipe, 0);
		else
			spawn_wake_and_close(wait_pipe, 0);

		aux = cb(arg);

		if (is_exec)
			spawn_wake_and_close(wait_pipe, -1);
		exit(aux);
	}

	close(wait_pipe[1]);

	if (aux >= 0)
		restore_ns(aux, &pid_ns);

	if (spawn_wait(wait_pipe))
		goto err;

	if (spawn_wait_and_close(wait_pipe) != INT_MIN)
		goto err;

	pr->pid = pid;

	return &pr->h;
err:
	xfree(pr);
	close(wait_pipe[0]);
	waitpid(pid, NULL, 0);
	return ERR_PTR(-1);
}