Ejemplo n.º 1
0
static int config_network_type(const char *key, char *value,
			       struct lxc_conf *lxc_conf)
{
	struct lxc_list *network = &lxc_conf->network;
	struct lxc_netdev *netdev;
	struct lxc_list *list;

	netdev = malloc(sizeof(*netdev));
	if (!netdev) {
		SYSERROR("failed to allocate memory");
		return -1;
	}

	memset(netdev, 0, sizeof(*netdev));
	lxc_list_init(&netdev->ipv4);
	lxc_list_init(&netdev->ipv6);

	list = malloc(sizeof(*list));
	if (!list) {
		SYSERROR("failed to allocate memory");
		return -1;
	}

	lxc_list_init(list);
	list->elem = netdev;

	lxc_list_add_tail(network, list);

	if (!strcmp(value, "veth"))
		netdev->type = LXC_NET_VETH;
	else if (!strcmp(value, "macvlan"))
		netdev->type = LXC_NET_MACVLAN;
	else if (!strcmp(value, "vlan"))
		netdev->type = LXC_NET_VLAN;
	else if (!strcmp(value, "phys"))
		netdev->type = LXC_NET_PHYS;
	else if (!strcmp(value, "empty"))
		netdev->type = LXC_NET_EMPTY;
	else {
		ERROR("invalid network type %s", value);
		return -1;
	}
	return 0;
}
Ejemplo n.º 2
0
/* This is a variation of get_list below it. This version allows two additional
 * features. If a list is passed to it, it adds to it. It allows for empty
 * entries (i.e. "group1,,group2") generating and empty list entry.
 */
static struct lxc_list *accumulate_list(char *input, char *delimiter,
					struct lxc_list *str_list)
{
	char *workstr = NULL;
	char *workptr = NULL;
	char *next_ptr = NULL;
	struct lxc_list *worklist;
	struct lxc_list *workstr_list;

	workstr = strdup(input);
	if (!workstr)
		return NULL;

	workstr_list = str_list;
	if (!workstr_list) {
		workstr_list = malloc(sizeof(*workstr_list));
		lxc_list_init(workstr_list);
	}

	for (workptr = workstr; workptr; workptr = next_ptr) {
		/* We can't use strtok_r here because it collapses multiple
		 * delimiters into 1 making empty fields impossible...
		 */
		next_ptr = strchr(workptr, *delimiter);
		if (next_ptr)
			*next_ptr++ = '\0';

		/* At this point, we'd like to check to see if this group is
		 * already contained in the list and ignore it if it is...  This
		 * also helps us with any corner cases where a string begins or
		 * ends with a delimiter.
		 */
		if (list_contains_entry(workptr, workstr_list)) {
			if (*workptr)
				fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr);
			else
				fprintf(stderr, "Duplicate NULL group in list - ignoring\n");
		} else {
			worklist = malloc(sizeof(*worklist));
			if (!worklist)
				break;

			worklist->elem = strdup(workptr);
			if (!worklist->elem) {
				free(worklist);
				break;
			}

			lxc_list_add_tail(workstr_list, worklist);
		}
	}

	free(workstr);

	return workstr_list;
}
Ejemplo n.º 3
0
static struct lxc_list *get_list(char *input, char *delimiter) {
	char *workstr = NULL;
	char *workptr = NULL;
	char *sptr = NULL;
	char *token = NULL;
	struct lxc_list *worklist;
	struct lxc_list *workstr_list;

	workstr_list = malloc(sizeof(*workstr_list));
	lxc_list_init(workstr_list);

	workstr = strdup(input);
	if (!workstr) {
		free(workstr_list);
		return NULL;
	}

	for (workptr = workstr;;workptr = NULL) {
		token = strtok_r(workptr, delimiter, &sptr);
		if (!token) {
			break;
		}

		worklist = malloc(sizeof(*worklist));
		if (!worklist)
			break;

		worklist->elem = strdup(token);
		if (!worklist->elem) {
			free(worklist);
			break;
		}

		lxc_list_add_tail(workstr_list, worklist);
	}

	free(workstr);

	return workstr_list;
}
Ejemplo n.º 4
0
int main(int argc, char *argv[])
{
	int c;
	unsigned long flags = CLONE_NEWUSER | CLONE_NEWNS;
	char ttyname0[256], ttyname1[256], ttyname2[256];
	int status;
	int ret;
	int pid;
	char *default_args[] = {"/bin/sh", NULL};
	char buf[1];
	int pipe1[2],  // child tells parent it has unshared
	    pipe2[2];  // parent tells child it is mapped and may proceed

	memset(ttyname0, '\0', sizeof(ttyname0));
	memset(ttyname1, '\0', sizeof(ttyname1));
	memset(ttyname2, '\0', sizeof(ttyname2));
	if (isatty(0)) {
		ret = readlink("/proc/self/fd/0", ttyname0, sizeof(ttyname0));
		if (ret < 0) {
			perror("unable to open stdin.");
			exit(1);
		}
		ret = readlink("/proc/self/fd/1", ttyname1, sizeof(ttyname1));
		if (ret < 0) {
			printf("Warning: unable to open stdout, continuing.");
			memset(ttyname1, '\0', sizeof(ttyname1));
		}
		ret = readlink("/proc/self/fd/2", ttyname2, sizeof(ttyname2));
		if (ret < 0) {
			printf("Warning: unable to open stderr, continuing.");
			memset(ttyname2, '\0', sizeof(ttyname2));
		}
	}

	lxc_list_init(&active_map);

	while ((c = getopt(argc, argv, "m:h")) != EOF) {
		switch (c) {
			case 'm': if (parse_map(optarg)) usage(argv[0]); break;
			case 'h':
			default:
				  usage(argv[0]);
		}
	};

	if (lxc_list_empty(&active_map)) {
		if (find_default_map()) {
			fprintf(stderr, "You have no allocated subuids or subgids\n");
			exit(1);
		}
	}

	argv = &argv[optind];
	argc = argc - optind;
	if (argc < 1) {
		argv = default_args;
		argc = 1;
	}

	if (pipe(pipe1) < 0 || pipe(pipe2) < 0) {
		perror("pipe");
		exit(1);
	}
	if ((pid = fork()) == 0) {
		// Child.

		close(pipe1[0]);
		close(pipe2[1]);
		opentty(ttyname0, 0);
		opentty(ttyname1, 1);
		opentty(ttyname2, 2);

		ret = unshare(flags);
		if (ret < 0) {
			perror("unshare");
			return 1;
		}
		buf[0] = '1';
		if (write(pipe1[1], buf, 1) < 1) {
			perror("write pipe");
			exit(1);
		}
		if (read(pipe2[0], buf, 1) < 1) {
			perror("read pipe");
			exit(1);
		}
		if (buf[0] != '1') {
			fprintf(stderr, "parent had an error, child exiting\n");
			exit(1);
		}

		close(pipe1[1]);
		close(pipe2[0]);
		return do_child((void*)argv);
	}

	close(pipe1[1]);
	close(pipe2[0]);
	if (read(pipe1[0], buf, 1) < 1) {
		perror("read pipe");
		exit(1);
	}

	buf[0] = '1';

	if (lxc_map_ids(&active_map, pid)) {
		fprintf(stderr, "error mapping child\n");
		ret = 0;
	}
	if (write(pipe2[1], buf, 1) < 0) {
		perror("write to pipe");
		exit(1);
	}

	if ((ret = waitpid(pid, &status, __WALL)) < 0) {
		printf("waitpid() returns %d, errno %d\n", ret, errno);
		exit(1);
	}

	exit(WEXITSTATUS(status));
}
Ejemplo n.º 5
0
int main(int argc, char *argv[])
{
	int c, pid, ret, status;
	char buf[1];
	int pipe_fds1[2], /* child tells parent it has unshared */
	    pipe_fds2[2]; /* parent tells child it is mapped and may proceed */
	unsigned long flags = CLONE_NEWUSER | CLONE_NEWNS;
	char ttyname0[256] = {0}, ttyname1[256] = {0}, ttyname2[256] = {0};
	char *default_args[] = {"/bin/sh", NULL};

	lxc_log_fd = STDERR_FILENO;

	if (isatty(STDIN_FILENO)) {
		ret = readlink("/proc/self/fd/0", ttyname0, sizeof(ttyname0));
		if (ret < 0) {
			CMD_SYSERROR("Failed to open stdin");
			_exit(EXIT_FAILURE);
		}

		ret = readlink("/proc/self/fd/1", ttyname1, sizeof(ttyname1));
		if (ret < 0) {
			CMD_SYSINFO("Failed to open stdout. Continuing");
			ttyname1[0] = '\0';
		}

		ret = readlink("/proc/self/fd/2", ttyname2, sizeof(ttyname2));
		if (ret < 0) {
			CMD_SYSINFO("Failed to open stderr. Continuing");
			ttyname2[0] = '\0';
		}
	}

	lxc_list_init(&active_map);

	while ((c = getopt(argc, argv, "m:h")) != EOF) {
		switch (c) {
		case 'm':
			ret = parse_map(optarg);
			if (ret < 0) {
				usage(argv[0]);
				_exit(EXIT_FAILURE);
			}
			break;
		case 'h':
			usage(argv[0]);
			_exit(EXIT_SUCCESS);
		default:
			usage(argv[0]);
			_exit(EXIT_FAILURE);
		}
	};

	if (lxc_list_empty(&active_map)) {
		ret = find_default_map();
		if (ret < 0) {
			fprintf(stderr, "Failed to find subuid or subgid allocation\n");
			_exit(EXIT_FAILURE);
		}
	}

	argv = &argv[optind];
	argc = argc - optind;
	if (argc < 1)
		argv = default_args;

	ret = pipe2(pipe_fds1, O_CLOEXEC);
	if (ret < 0) {
		CMD_SYSERROR("Failed to open new pipe");
		_exit(EXIT_FAILURE);
	}

	ret = pipe2(pipe_fds2, O_CLOEXEC);
	if (ret < 0) {
		CMD_SYSERROR("Failed to open new pipe");
		close(pipe_fds1[0]);
		close(pipe_fds1[1]);
		_exit(EXIT_FAILURE);
	}

	pid = fork();
	if (pid < 0) {
		close(pipe_fds1[0]);
		close(pipe_fds1[1]);
		close(pipe_fds2[0]);
		close(pipe_fds2[1]);
		_exit(EXIT_FAILURE);
	}

	if (pid == 0) {
		close(pipe_fds1[0]);
		close(pipe_fds2[1]);

		opentty(ttyname0, STDIN_FILENO);
		opentty(ttyname1, STDOUT_FILENO);
		opentty(ttyname2, STDERR_FILENO);

		ret = unshare(flags);
		if (ret < 0) {
			CMD_SYSERROR("Failed to unshare mount and user namespace");
			close(pipe_fds1[1]);
			close(pipe_fds2[0]);
			_exit(EXIT_FAILURE);
		}

		buf[0] = '1';
		ret = lxc_write_nointr(pipe_fds1[1], buf, 1);
		if (ret != 1) {
			CMD_SYSERROR("Failed to write to pipe file descriptor %d",
				     pipe_fds1[1]);
			close(pipe_fds1[1]);
			close(pipe_fds2[0]);
			_exit(EXIT_FAILURE);
		}

		ret = lxc_read_nointr(pipe_fds2[0], buf, 1);
		if (ret != 1) {
			CMD_SYSERROR("Failed to read from pipe file descriptor %d",
				     pipe_fds2[0]);
			close(pipe_fds1[1]);
			close(pipe_fds2[0]);
			_exit(EXIT_FAILURE);
		}

		close(pipe_fds1[1]);
		close(pipe_fds2[0]);

		if (buf[0] != '1') {
			fprintf(stderr, "Received unexpected value from parent process\n");
			_exit(EXIT_FAILURE);
		}

		ret = do_child((void *)argv);
		if (ret < 0)
			_exit(EXIT_FAILURE);

		_exit(EXIT_SUCCESS);
	}

	close(pipe_fds1[1]);
	close(pipe_fds2[0]);

	ret = lxc_read_nointr(pipe_fds1[0], buf, 1);
	if (ret <= 0)
		CMD_SYSERROR("Failed to read from pipe file descriptor %d", pipe_fds1[0]);

	buf[0] = '1';

	ret = lxc_map_ids(&active_map, pid);
	if (ret < 0)
		fprintf(stderr, "Failed to write id mapping for child process\n");

	ret = lxc_write_nointr(pipe_fds2[1], buf, 1);
	if (ret < 0) {
		CMD_SYSERROR("Failed to write to pipe file descriptor %d", pipe_fds2[1]);
		_exit(EXIT_FAILURE);
	}

	ret = waitpid(pid, &status, __WALL);
	if (ret < 0) {
		CMD_SYSERROR("Failed to wait on child process");
		_exit(EXIT_FAILURE);
	}

	_exit(WEXITSTATUS(status));
}
Ejemplo n.º 6
0
static int config_network_ipv4(const char *key, char *value,
			       struct lxc_conf *lxc_conf)
{
	struct lxc_netdev *netdev;
	struct lxc_inetdev *inetdev;
	struct lxc_list *list;
	char *cursor, *slash, *addr = NULL, *bcast = NULL, *prefix = NULL;

	netdev = network_netdev(key, value, &lxc_conf->network);
	if (!netdev)
		return -1;

	inetdev = malloc(sizeof(*inetdev));
	if (!inetdev) {
		SYSERROR("failed to allocate ipv4 address");
		return -1;
	}
	memset(inetdev, 0, sizeof(*inetdev));

	list = malloc(sizeof(*list));
	if (!list) {
		SYSERROR("failed to allocate memory");
		return -1;
	}

	lxc_list_init(list);
	list->elem = inetdev;

	addr = value;

	cursor = strstr(addr, " ");
	if (cursor) {
		*cursor = '\0';
		bcast = cursor + 1;
	}

	slash = strstr(addr, "/");
	if (slash) {
		*slash = '\0';
		prefix = slash + 1;
	}

	if (!addr) {
		ERROR("no address specified");
		return -1;
	}

	if (!inet_pton(AF_INET, addr, &inetdev->addr)) {
		SYSERROR("invalid ipv4 address: %s", value);
		return -1;
	}

	if (bcast && !inet_pton(AF_INET, bcast, &inetdev->bcast)) {
		SYSERROR("invalid ipv4 broadcast address: %s", value);
		return -1;
	}

	/* no prefix specified, determine it from the network class */
	inetdev->prefix = prefix ? atoi(prefix) :
		config_ip_prefix(&inetdev->addr);

	/* if no broadcast address, let compute one from the
	 * prefix and address
	 */
	if (!bcast) {
		inetdev->bcast.s_addr = inetdev->addr.s_addr;
		inetdev->bcast.s_addr |=
			htonl(INADDR_BROADCAST >>  inetdev->prefix);
	}