Beispiel #1
0
int main(int argc, char *argv[])
{
	int ret;
	pid_t pid;
	lxc_attach_options_t attach_options = LXC_ATTACH_OPTIONS_DEFAULT;
	lxc_attach_command_t command;

	ret = lxc_caps_init();
	if (ret)
		return ret;

	ret = lxc_arguments_parse(&my_args, argc, argv);
	if (ret)
		return ret;

	if (!my_args.log_file)
		my_args.log_file = "none";

	ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
			   my_args.progname, my_args.quiet, my_args.lxcpath[0]);
	if (ret)
		return ret;
	lxc_log_options_no_override();

	if (remount_sys_proc)
		attach_options.attach_flags |= LXC_ATTACH_REMOUNT_PROC_SYS;
	if (elevated_privileges)
		attach_options.attach_flags &= ~(elevated_privileges);
	attach_options.namespaces = namespace_flags;
	attach_options.personality = new_personality;
	attach_options.env_policy = env_policy;
	attach_options.extra_env_vars = extra_env;
	attach_options.extra_keep_env = extra_keep;

	if (my_args.argc) {
		command.program = my_args.argv[0];
		command.argv = (char**)my_args.argv;
		ret = lxc_attach(my_args.name, my_args.lxcpath[0], lxc_attach_run_command, &command, &attach_options, &pid);
	} else {
		ret = lxc_attach(my_args.name, my_args.lxcpath[0], lxc_attach_run_shell, NULL, &attach_options, &pid);
	}

	if (ret < 0)
		return -1;

	ret = lxc_wait_for_pid_status(pid);
	if (ret < 0)
		return -1;

	if (WIFEXITED(ret))
		return WEXITSTATUS(ret);

	return -1;
}
Beispiel #2
0
int main(int argc, char *argv[])
{
	int opt, status;
	int ret;
	char *namespaces = NULL;
	char **args;
	int flags = 0;
	int daemonize = 0;
	uid_t uid = 0; /* valid only if (flags & CLONE_NEWUSER) */
	pid_t pid;
	struct my_iflist *tmpif, *my_iflist = NULL;
	struct start_arg start_arg = {
		.args = &args,
		.uid = &uid,
		.setuid = false,
		.flags = &flags,
		.want_hostname = NULL,
		.want_default_mounts = 0,
	};

	while ((opt = getopt(argc, argv, "s:u:hH:i:dM")) != -1) {
		switch (opt) {
		case 's':
			namespaces = optarg;
			break;
		case 'i':
			if (!(tmpif = malloc(sizeof(*tmpif)))) {
				perror("malloc");
				exit(1);
			}
			tmpif->mi_ifname = optarg;
			tmpif->mi_next = my_iflist;
			my_iflist = tmpif;
			break;
		case 'd':
			daemonize = 1;
			break;
		case 'M':
			start_arg.want_default_mounts = 1;
			break;
		case 'H':
			start_arg.want_hostname = optarg;
			break;
		case 'h':
			usage(argv[0]);
			break;
		case 'u':
			if (!lookup_user(optarg, &uid))
				return 1;
			start_arg.setuid = true;
		}
	}

	if (argv[optind] == NULL) {
		ERROR("a command to execute in the new namespace is required");
		return 1;
	}

	args = &argv[optind];

	ret = lxc_caps_init();
	if (ret)
		return 1;

	ret = lxc_fill_namespace_flags(namespaces, &flags);
	if (ret)
		usage(argv[0]);

	if (!(flags & CLONE_NEWNET) && my_iflist) {
		ERROR("-i <interfacename> needs -s NETWORK option");
		return 1;
	}

	if (!(flags & CLONE_NEWUTS) && start_arg.want_hostname) {
		ERROR("-H <hostname> needs -s UTSNAME option");
		return 1;
	}

	if (!(flags & CLONE_NEWNS) && start_arg.want_default_mounts) {
		ERROR("-M needs -s MOUNT option");
		return 1;
	}

	pid = lxc_clone(do_start, &start_arg, flags);
	if (pid < 0) {
		ERROR("failed to clone");
		return 1;
	}

	if (my_iflist) {
		for (tmpif = my_iflist; tmpif; tmpif = tmpif->mi_next) {
			if (lxc_netdev_move_by_name(tmpif->mi_ifname, pid) < 0)
				fprintf(stderr,"Could not move interface %s into container %d: %s\n", tmpif->mi_ifname, pid, strerror(errno));
		}
	}

	if (daemonize)
		exit(0);

	if (waitpid(pid, &status, 0) < 0) {
		ERROR("failed to wait for '%d'", pid);
		return 1;
	}

	return  lxc_error_set_and_log(pid, status);
}
Beispiel #3
0
int main(int argc, char *argv[])
{
	pid_t pid;
	int err;
	char **aargv;
	sigset_t mask, omask;
	int i, have_status = 0, shutdown = 0;
	int opt;
	char *lxcpath = NULL, *name = NULL, *logpriority = NULL;

	while ((opt = getopt_long(argc, argv, "n:l:qP:", options, NULL)) != -1) {
		switch(opt) {
		case 'n':
			name = optarg;
			break;
		case 'l':
			logpriority = optarg;
			break;
		case 'q':
			quiet = 1;
 			break;
		case 'P':
			lxcpath = optarg;
			break;
		default: /* '?' */
			usage();
			exit(EXIT_FAILURE);
		}
	}

	if (lxc_caps_init())
		exit(EXIT_FAILURE);

	err = lxc_log_init(name, name ? NULL : "none", logpriority,
			   basename(argv[0]), quiet, lxcpath);
	if (err < 0)
		exit(EXIT_FAILURE);
	lxc_log_options_no_override();

	if (!argv[optind]) {
		ERROR("missing command to launch");
		exit(EXIT_FAILURE);
	}

	aargv = &argv[optind];

        /*
	 * mask all the signals so we are safe to install a
	 * signal handler and to fork
	 */
	if (sigfillset(&mask) ||
	    sigdelset(&mask, SIGILL) ||
	    sigdelset(&mask, SIGSEGV) ||
	    sigdelset(&mask, SIGBUS) ||
	    sigprocmask(SIG_SETMASK, &mask, &omask)) {
		SYSERROR("failed to set signal mask");
		exit(EXIT_FAILURE);
	}

	for (i = 1; i < NSIG; i++) {
		struct sigaction act;

		/* Exclude some signals: ILL, SEGV and BUS are likely to
		 * reveal a bug and we want a core. STOP and KILL cannot be
		 * handled anyway: they're here for documentation.
		 */
		if (i == SIGILL ||
		    i == SIGSEGV ||
		    i == SIGBUS ||
		    i == SIGSTOP ||
		    i == SIGKILL ||
		    i == 32 || i == 33)
			continue;

		if (sigfillset(&act.sa_mask) ||
		    sigdelset(&act.sa_mask, SIGILL) ||
		    sigdelset(&act.sa_mask, SIGSEGV) ||
		    sigdelset(&act.sa_mask, SIGBUS) ||
		    sigdelset(&act.sa_mask, SIGSTOP) ||
		    sigdelset(&act.sa_mask, SIGKILL)) {
			ERROR("failed to set signal");
			exit(EXIT_FAILURE);
		}

		act.sa_flags = 0;
		act.sa_handler = interrupt_handler;
		if (sigaction(i, &act, NULL) && errno != EINVAL) {
			SYSERROR("failed to sigaction");
			exit(EXIT_FAILURE);
		}
	}

	lxc_setup_fs();

	if (lxc_caps_reset())
		exit(EXIT_FAILURE);

	pid = fork();

	if (pid < 0)
		exit(EXIT_FAILURE);

	if (!pid) {

		/* restore default signal handlers */
		for (i = 1; i < NSIG; i++)
			signal(i, SIG_DFL);

		if (sigprocmask(SIG_SETMASK, &omask, NULL)) {
			SYSERROR("failed to set signal mask");
			exit(EXIT_FAILURE);
		}

		NOTICE("about to exec '%s'", aargv[0]);

		execvp(aargv[0], aargv);
		ERROR("failed to exec: '%s' : %m", aargv[0]);
		exit(err);
	}

	/* let's process the signals now */
	if (sigdelset(&omask, SIGALRM) ||
	    sigprocmask(SIG_SETMASK, &omask, NULL)) {
		SYSERROR("failed to set signal mask");
		exit(EXIT_FAILURE);
	}

	/* no need of other inherited fds but stderr */
	close(fileno(stdin));
	close(fileno(stdout));

	err = EXIT_SUCCESS;
	for (;;) {
		int status;
		pid_t waited_pid;

		switch (was_interrupted) {

		case 0:
			break;

		case SIGTERM:
			if (!shutdown) {
				shutdown = 1;
				kill(-1, SIGTERM);
				alarm(1);
			}
			break;

		case SIGALRM:
			kill(-1, SIGKILL);
			break;

		default:
			kill(pid, was_interrupted);
			break;
		}

		was_interrupted = 0;
		waited_pid = wait(&status);
		if (waited_pid < 0) {
			if (errno == ECHILD)
				goto out;
			if (errno == EINTR)
				continue;

			ERROR("failed to wait child : %s",
			      strerror(errno));
			goto out;
		}

		/* reset timer each time a process exited */
		if (shutdown)
			alarm(1);

		/*
		 * keep the exit code of started application
		 * (not wrapped pid) and continue to wait for
		 * the end of the orphan group.
		 */
		if (waited_pid == pid && !have_status) {
			err = lxc_error_set_and_log(waited_pid, status);
			have_status = 1;
		}
	}
out:
	return err;
}
Beispiel #4
0
int main(int argc, char *argv[])
{
	int opt, status;
	int ret;
	char *namespaces = NULL;
	char **args;
	int flags = 0;
	uid_t uid = -1; /* valid only if (flags & CLONE_NEWUSER) */
	pid_t pid;

	struct start_arg start_arg = {
		.args = &args,
		.uid = &uid,
		.flags = &flags,
	};

	while ((opt = getopt(argc, argv, "s:u:h")) != -1) {
		switch (opt) {
		case 's':
			namespaces = optarg;
			break;
		case 'h':
			usage(argv[0]);
		case 'u':
			uid = lookup_user(optarg);
			if (uid == -1)
				return 1;
		}
	}

	if (argv[optind] == NULL) {
		ERROR("a command to execute in the new namespace is required");
		return 1;
	}

	args = &argv[optind];

	ret = lxc_caps_init();
	if (ret)
		return ret;

	ret = lxc_fill_namespace_flags(namespaces, &flags);
	if (ret)
		usage(argv[0]);

	if (!(flags & CLONE_NEWUSER) && uid != -1) {
		ERROR("-u <uid> needs -s USER option");
		return 1;
	}

	pid = lxc_clone(do_start, &start_arg, flags);
	if (pid < 0) {
		ERROR("failed to clone");
		return -1;
	}

	if (waitpid(pid, &status, 0) < 0) {
		ERROR("failed to wait for '%d'", pid);
		return -1;
	}

	return  lxc_error_set_and_log(pid, status);
}