Exemplo n.º 1
0
static int loopback_init(void)
{
	loopback_address = inet_addr("127.0.0.1");
	loopback_netmask = inet_addr("255.0.0.0");

	setup_loopback();

	setup_hostname();

	connman_utsname_driver_register(&loopback_driver);

	return 0;
}
Exemplo n.º 2
0
int main(int argc, char *argv[]) {
	int rc, i;

	pid_t pid  = -1;
	pid_t ppid = getpid();

	uid_t uid = -1;
	gid_t gid = -1;

	_free_ char *user   = NULL;
	_free_ char *dest   = NULL;
	_free_ char *change = NULL;
	_free_ char *env    = NULL;
	_free_ char *cgroup = NULL;

	_close_ int master_fd = -1;

	char *master_name;

	int detach  = 0;
	int keepenv = 0;

	siginfo_t status;

	while ((rc = getopt_long(argc, argv, short_opts, long_opts, &i)) !=-1) {
		switch (rc) {
			case 'm':
				validate_optlist("--mount", optarg);

				add_mount_from_spec(optarg);
				break;

			case 'n':
				clone_flags |= CLONE_NEWNET;

				if (optarg != NULL) {
					validate_optlist("--netif", optarg);

					add_netif_from_spec(optarg);
				}
				break;

			case 'u':
				clone_flags |= CLONE_NEWUSER;

				freep(&user);

				user = strdup(optarg);
				break;

			case 'r':
				freep(&dest);

				dest = realpath(optarg, NULL);
				if (dest == NULL) sysf_printf("realpath()");
				break;

			case 'c':
				freep(&change);

				change = strdup(optarg);
				break;

			case 'g':
				validate_optlist("--cgroup", optarg);
				validate_cgroup_spec(optarg);

				freep(&change);

				cgroup = strdup(optarg);
				break;

			case 'd':
				detach = 1;
				break;

			case 'a': {
				char *end = NULL;
				pid = strtol(optarg, &end, 10);
				if (*end != '\0')
					fail_printf("Invalid value '%s' for --attach", optarg);
				break;
			}

			case 's': {
				validate_optlist("--setenv", optarg);

				if (env != NULL) {
					char *tmp = env;

					rc = asprintf(&env, "%s,%s", env, optarg);
					if (rc < 0) fail_printf("OOM");

					freep(&tmp);
				} else {
					env = strdup(optarg);
				}

				break;
			}

			case 'k':
				keepenv = 1;
				break;

			case 'U':
				clone_flags &= ~(CLONE_NEWUSER);
				break;

			case 'M':
				clone_flags &= ~(CLONE_NEWNS);
				break;

			case 'N':
				clone_flags &= ~(CLONE_NEWNET);
				break;

			case 'I':
				clone_flags &= ~(CLONE_NEWIPC);
				break;

			case 'H':
				clone_flags &= ~(CLONE_NEWUTS);
				break;

			case 'P':
				clone_flags &= ~(CLONE_NEWPID);
				break;

			case '?':
			case 'h':
				help();
				return 0;
		}
	}

	if (pid != -1) {
		master_fd = recv_pty(pid);
		if (master_fd < 0) fail_printf("Invalid PID '%u'", pid);

		pid = -1;
		goto process_fd;
	}

	if (user == NULL) {
		user = strdup("root");
		if (user == NULL) fail_printf("OOM");
	}

	open_master_pty(&master_fd, &master_name);

	uid = getuid();
	gid = getgid();

	if (detach == 1)
		do_daemonize();

	pid = do_clone();

	if (pid == 0) {
		closep(&master_fd);

		open_slave_pty(master_name);

		rc = setsid();
		if (rc < 0) sysf_printf("setsid()");

		rc = prctl(PR_SET_PDEATHSIG, SIGKILL);
		if (rc < 0) sysf_printf("prctl(PR_SET_PDEATHSIG)");

		if (clone_flags & CLONE_NEWUSER)
			map_user_to_user(uid, gid, user);

		do_cgroup(cgroup, ppid);

		do_mount(dest);

		if (dest != NULL) {
			copy_nodes(dest);

			make_ptmx(dest);

			make_symlinks(dest);

			make_console(dest, master_name);

			do_chroot(dest);
		}

		if (clone_flags & CLONE_NEWNET)
			setup_loopback();

		umask(0022);

		/* TODO: drop capabilities */

		do_user(user);

		if (change != NULL) {
			rc = chdir(change);
			if (rc < 0) sysf_printf("chdir()");
		}

		if (dest != NULL) {
			char *term = getenv("TERM");

			if (keepenv == 0)
				clearenv();

			setenv("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
			setenv("USER", user, 1);
			setenv("LOGNAME", user, 1);
			setenv("TERM", term, 1);
		}

		if (env != NULL) {
			size_t i, c;

			_free_ char **vars = NULL;

			_free_ char *tmp = strdup(env);
			if (tmp == NULL) fail_printf("OOM");

			c = split_str(tmp, &vars, ",");

			for (i = 0; i < c; i++) {
				rc = putenv(strdup(vars[i]));
				if (rc != 0) sysf_printf("putenv()");
			}
		}

		setenv("container", "pflask", 1);

		if (argc > optind)
			rc = execvpe(argv[optind], argv + optind, environ);
		else
			rc = execle("/bin/bash", "-bash", NULL, environ);

		if (rc < 0) sysf_printf("exec()");
	}

	do_netif(pid);

process_fd:
	if (detach == 1)
		serve_pty(master_fd);
	else
		process_pty(master_fd);

	if (pid == -1)
		return 0;

	kill(pid, SIGKILL);

	rc = waitid(P_PID, pid, &status, WEXITED);
	if (rc < 0) sysf_printf("waitid()");

	switch (status.si_code) {
		case CLD_EXITED:
			if (status.si_status != 0)
				err_printf("Child failed with code '%d'",
				           status.si_status);
			else
				ok_printf("Child exited");
			break;

		case CLD_KILLED:
			err_printf("Child was terminated");
			break;

		default:
			err_printf("Child failed");
			break;
	}

	undo_cgroup(cgroup, ppid);

	return status.si_status;
}