示例#1
0
static void *cgm_init(const char *name)
{
	struct cgm_data *d;

	d = malloc(sizeof(*d));
	if (!d)
		return NULL;

	if (!cgm_dbus_connect()) {
		ERROR("Error connecting to cgroup manager");
		goto err1;
	}

	memset(d, 0, sizeof(*d));
	d->name = strdup(name);
	if (!d->name) {
		cgm_dbus_disconnect();
		goto err1;
	}

	d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");

	// cgm_create immediately gets called so keep the connection open
	return d;

err1:
	free(d);
	return NULL;
}
示例#2
0
文件: cgmanager.c 项目: bhanug/lxc
/*
 * Make sure that all the controllers are writeable.
 * If any are not, then
 *   - if they are listed in lxc.cgroup.use, refuse to start
 *   - else if they are crucial subsystems, refuse to start
 *   - else warn and do not use them
 */
static bool verify_final_subsystems(const char *cgroup_use)
{
	int i;
	bool dropped_any = false;
	bool bret = false;
	const char *cgroup_pattern;
	char tmpnam[50], *probe;

	if (!cgm_dbus_connect()) {
		ERROR("Error connecting to cgroup manager");
		return false;
	}

	cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
	i = snprintf(tmpnam, 50, "lxcprobe-%d", getpid());
	if (i < 0 || i >= 50) {
		ERROR("Attack - format string modified?");
		return false;
	}
	probe = lxc_string_replace("%n", tmpnam, cgroup_pattern);
	if (!probe)
		goto out;

	i = 0;
	while (i < nr_subsystems) {
		char *p = get_last_controller_in_list(subsystems[i]);

		if (!subsys_is_writeable(p, probe)) {
			if (is_crucial_subsys(p)) {
				ERROR("Cannot write to crucial subsystem %s\n",
					subsystems[i]);
				goto out;
			}
			if (cgroup_use && any_in_comma_list(subsystems[i], cgroup_use)) {
				ERROR("Cannot write to subsystem %s which is requested in lxc.cgroup.use\n",
					subsystems[i]);
				goto out;
			}
			WARN("Cannot write to subsystem %s, continuing with out it\n",
				subsystems[i]);
			dropped_any = true;
			drop_subsystem(i);
		} else {
			cgm_remove_cgroup(subsystems[i], probe);
			i++;
		}
	}

	if (dropped_any)
		cgm_all_controllers_same = false;
	bret = true;

out:
	free(probe);
	cgm_dbus_disconnect();
	return bret;
}
示例#3
0
static void *cgm_init(const char *name)
{
    struct cgm_data *d;

    if (!cgm_dbus_connect()) {
        ERROR("Error connecting to cgroup manager");
        return NULL;
    }
    d = malloc(sizeof(*d));
    if (!d) {
        cgm_dbus_disconnect();
        return NULL;
    }

    memset(d, 0, sizeof(*d));
    d->name = strdup(name);
    if (!d->name) {
        cgm_dbus_disconnect();
        goto err1;
    }

    /* if we are running as root, use system cgroup pattern, otherwise
     * just create a cgroup under the current one. But also fall back to
     * that if for some reason reading the configuration fails and no
     * default value is available
     */
    if (geteuid() == 0)
        d->cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
    if (!d->cgroup_pattern)
        d->cgroup_pattern = "%n";
    // cgm_create immediately gets called so keep the connection open
    return d;

err1:
    free(d);
    return NULL;
}
示例#4
0
static bool collect_subsytems(void)
{
	char *line = NULL;
	nih_local char **cgm_subsys_list = NULL;
	size_t sz = 0;
	FILE *f = NULL;

	if (subsystems) // already initialized
		return true;

	subsystems_inone = malloc(2 * sizeof(char *));
	if (!subsystems_inone)
		return false;
	subsystems_inone[0] = "all";
	subsystems_inone[1] = NULL;

	if (lxc_list_controllers(&cgm_subsys_list)) {
		while (cgm_subsys_list[nr_subsystems]) {
			char **tmp = NIH_MUST( realloc(subsystems,
						(nr_subsystems+2)*sizeof(char *)) );
			tmp[nr_subsystems] = NIH_MUST(
					strdup(cgm_subsys_list[nr_subsystems++]) );
			subsystems = tmp;
		}
		if (nr_subsystems)
			subsystems[nr_subsystems] = NULL;
		goto collected;
	}

	INFO("cgmanager_list_controllers failed, falling back to /proc/self/cgroups");
	f = fopen_cloexec("/proc/self/cgroup", "r");
	if (!f) {
		f = fopen_cloexec("/proc/1/cgroup", "r");
		if (!f)
			return false;
	}
	while (getline(&line, &sz, f) != -1) {
		/* file format: hierarchy:subsystems:group,
		 * with multiple subsystems being ,-separated */
		char *slist, *end, *p, *saveptr = NULL, **tmp;

		if (!line[0])
			continue;

		slist = strchr(line, ':');
		if (!slist)
			continue;
		slist++;
		end = strchr(slist, ':');
		if (!end)
			continue;
		*end = '\0';

		for (p = strtok_r(slist, ",", &saveptr);
				p;
				p = strtok_r(NULL, ",", &saveptr)) {
			tmp = realloc(subsystems, (nr_subsystems+2)*sizeof(char *));
			if (!tmp)
				goto out_free;

			subsystems = tmp;
			tmp[nr_subsystems] = strdup(p);
			tmp[nr_subsystems+1] = NULL;
			if (!tmp[nr_subsystems])
				goto out_free;
			nr_subsystems++;
		}
	}
	fclose(f);
	f = NULL;

	free(line);
	line = NULL;

collected:
	if (!nr_subsystems) {
		ERROR("No cgroup subsystems found");
		return false;
	}

	/* make sure that cgroup.use can be and is honored */
	const char *cgroup_use = lxc_global_config_value("lxc.cgroup.use");
	if (!cgroup_use && errno != 0)
		goto final_verify;
	if (cgroup_use) {
		if (!verify_and_prune(cgroup_use)) {
			free_subsystems();
			return false;
		}
		subsystems_inone[0] = NIH_MUST( strdup(cgroup_use) );
		cgm_all_controllers_same = false;
	}

final_verify:
	return verify_final_subsystems(cgroup_use);

out_free:
	free(line);
	if (f)
		fclose(f);
	free_subsystems();
	return false;
}
示例#5
0
文件: utils.c 项目: is00hcw/lxc
const char *default_cgroup_pattern(void)
{
	return lxc_global_config_value("cgroup.pattern");
}
示例#6
0
文件: utils.c 项目: is00hcw/lxc
const char *default_cgroup_use(void)
{
	return lxc_global_config_value("cgroup.use");
}
示例#7
0
文件: utils.c 项目: is00hcw/lxc
const char *default_lxc_path(void)
{
	return lxc_global_config_value("lxcpath");
}
示例#8
0
文件: utils.c 项目: is00hcw/lxc
const char *default_zfs_root(void)
{
	return lxc_global_config_value("zfsroot");
}
示例#9
0
文件: utils.c 项目: is00hcw/lxc
const char *default_lvm_thin_pool(void)
{
	return lxc_global_config_value("lvm_thin_pool");
}
示例#10
0
文件: utils.c 项目: is00hcw/lxc
const char *default_lvm_vg(void)
{
	return lxc_global_config_value("lvm_vg");
}
示例#11
0
文件: arguments.c 项目: d4s/lxc
extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
			       char *const argv[])
{
	int ret = 0;
	char shortopts[256];

	ret = build_shortopts(args->options, shortopts, sizeof(shortopts));
	if (ret < 0) {
		lxc_error(args, "build_shortopts() failed : %s",
			  strerror(errno));
		return ret;
	}

	while (true) {
		int c;
		int index = 0;

		c = getopt_long(argc, argv, shortopts, args->options, &index);
		if (c == -1)
			break;
		switch (c) {
		case 'n':
			args->name = optarg;
			break;
		case 'o':
			args->log_file = optarg;
			break;
		case 'l':
			args->log_priority = optarg;
			break;
		case 'q':
			args->quiet = 1;
			break;
		case OPT_RCFILE:
			args->rcfile = optarg;
			break;
		case 'P':
			remove_trailing_slashes(optarg);
			ret = lxc_arguments_lxcpath_add(args, optarg);
			if (ret < 0)
				return ret;
			break;
		case OPT_USAGE:
			print_usage(args->options, args);
		case OPT_VERSION:
			print_version();
		case '?':
			print_help(args, 1);
		case 'h':
			print_help(args, 0);
		default:
			if (args->parser) {
				ret = args->parser(args, c, optarg);
				if (ret)
					goto error;
			}
		}
	}

	/*
	 * Reclaim the remaining command arguments
	 */
	args->argv = &argv[optind];
	args->argc = argc - optind;

	/* If no lxcpaths were given, use default */
	if (!args->lxcpath_cnt) {
		ret = lxc_arguments_lxcpath_add(
		    args, lxc_global_config_value("lxc.lxcpath"));
		if (ret < 0)
			return ret;
	}

	/* Check the command options */

	if (!args->name && strcmp(args->progname, "lxc-autostart") != 0) {
		lxc_error(args, "missing container name, use --name option");
		return -1;
	}

	if (args->checker)
		ret = args->checker(args);
error:
	if (ret)
		lxc_error(args, "could not parse command line");
	return ret;
}
示例#12
0
文件: log.c 项目: Azendale/lxc
/*
 * lxc_log_init:
 * Called from lxc front-end programs (like lxc-create, lxc-start) to
 * initalize the log defaults.
 */
extern int lxc_log_init(const char *name, const char *file,
			const char *priority, const char *prefix, int quiet,
			const char *lxcpath)
{
	int lxc_priority = LXC_LOG_PRIORITY_ERROR;
	int ret;

	if (lxc_log_fd != -1) {
		WARN("lxc_log_init called with log already initialized");
		return 0;
	}

	if (priority)
		lxc_priority = lxc_log_priority_to_int(priority);

	if (!lxc_loglevel_specified) {
		lxc_log_category_lxc.priority = lxc_priority;
		lxc_loglevel_specified = 1;
	}

	if (!lxc_quiet_specified) {
		if (!quiet)
			lxc_log_category_lxc.appender->next = &log_appender_stderr;
	}

	if (prefix)
		lxc_log_set_prefix(prefix);

	if (file) {
		if (strcmp(file, "none") == 0)
			return 0;
		ret = __lxc_log_set_file(file, 1);
		lxc_log_use_global_fd = 1;
	} else {
		/* if no name was specified, there nothing to do */
		if (!name)
			return 0;

		ret = -1;

		if (!lxcpath)
			lxcpath = LOGPATH;

		/* try LOGPATH if lxcpath is the default for the privileged containers */
		if (!geteuid() && strcmp(lxcpath, lxc_global_config_value("lxc.lxcpath")) == 0)
			ret = _lxc_log_set_file(name, NULL, 0);

		/* try in lxcpath */
		if (ret < 0)
			ret = _lxc_log_set_file(name, lxcpath, 1);

		/* try LOGPATH in case its writable by the caller */
		if (ret < 0)
			ret = _lxc_log_set_file(name, NULL, 0);
	}

	/*
	 * If !file, that is, if the user did not request this logpath, then
	 * ignore failures and continue logging to console
	 */
	if (!file && ret != 0) {
		INFO("Ignoring failure to open default logfile.");
		ret = 0;
	}

	return ret;
}
示例#13
0
int zfs_clone(const char *opath, const char *npath, const char *oname,
		const char *nname, const char *lxcpath, int snapshot)
{
	// use the 'zfs list | grep opath' entry to get the zfsroot
	char output[MAXPATHLEN], option[MAXPATHLEN];
	char *p;
	const char *zfsroot = output;
	int ret;
	pid_t pid;

	if (zfs_list_entry(opath, output, MAXPATHLEN)) {
		// zfsroot is output up to ' '
		if ((p = strchr(output, ' ')) == NULL)
			return -1;
		*p = '\0';

		if ((p = strrchr(output, '/')) == NULL)
			return -1;
		*p = '\0';
	} else {
		zfsroot = lxc_global_config_value("lxc.bdev.zfs.root");
	}

	ret = snprintf(option, MAXPATHLEN, "-omountpoint=%s/%s/rootfs", lxcpath, nname);
	if (ret < 0  || ret >= MAXPATHLEN)
		return -1;

	// zfs create -omountpoint=$lxcpath/$lxcname $zfsroot/$nname
	if (!snapshot) {
		if ((pid = fork()) < 0)
			return -1;
		if (!pid) {
			char dev[MAXPATHLEN];
			ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, nname);
			if (ret < 0  || ret >= MAXPATHLEN)
				exit(EXIT_FAILURE);
			execlp("zfs", "zfs", "create", option, dev, NULL);
			exit(EXIT_FAILURE);
		}
		return wait_for_pid(pid);
	} else {
		// if snapshot, do
		// 'zfs snapshot zfsroot/oname@nname
		// zfs clone zfsroot/oname@nname zfsroot/nname
		char path1[MAXPATHLEN], path2[MAXPATHLEN];

		ret = snprintf(path1, MAXPATHLEN, "%s/%s@%s", zfsroot,
				oname, nname);
		if (ret < 0 || ret >= MAXPATHLEN)
			return -1;
		(void) snprintf(path2, MAXPATHLEN, "%s/%s", zfsroot, nname);

		// if the snapshot exists, delete it
		if ((pid = fork()) < 0)
			return -1;
		if (!pid) {
			execlp("zfs", "zfs", "destroy", path1, NULL);
			exit(EXIT_FAILURE);
		}
		// it probably doesn't exist so destroy probably will fail.
		(void) wait_for_pid(pid);

		// run first (snapshot) command
		if ((pid = fork()) < 0)
			return -1;
		if (!pid) {
			execlp("zfs", "zfs", "snapshot", path1, NULL);
			exit(EXIT_FAILURE);
		}
		if (wait_for_pid(pid) < 0)
			return -1;

		// run second (clone) command
		if ((pid = fork()) < 0)
			return -1;
		if (!pid) {
			execlp("zfs", "zfs", "clone", option, path1, path2, NULL);
			exit(EXIT_FAILURE);
		}
		return wait_for_pid(pid);
	}
}