Exemple #1
0
static int do_child(void *vargv)
{
	char **argv = (char **)vargv;

	// Assume we want to become root
	if (setgid(0) < 0) {
		perror("setgid");
		return -1;
	}
	if (setuid(0) < 0) {
		perror("setuid");
		return -1;
	}
	if (setgroups(0, NULL) < 0) {
		perror("setgroups");
		return -1;
	}
	if (unshare(CLONE_NEWNS) < 0) {
		perror("unshare CLONE_NEWNS");
		return -1;
	}
	if (detect_shared_rootfs()) {
		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
			printf("Failed to make / rslave");
			return -1;
		}
	}
	execvp(argv[0], argv);
	perror("execvpe");
	return -1;
}
Exemple #2
0
static int do_child(void *vargv)
{
	int ret;
	char **argv = (char **)vargv;

	/* Assume we want to become root */
	if (!lxc_switch_uid_gid(0, 0))
		return -1;

	if (!lxc_setgroups(0, NULL))
		return -1;

	ret = unshare(CLONE_NEWNS);
	if (ret < 0) {
		CMD_SYSERROR("Failed to unshare mount namespace");
		return -1;
	}

	if (detect_shared_rootfs()) {
		ret = mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL);
		if (ret < 0) {
			CMD_SYSINFO("Failed to make \"/\" rslave");
			return -1;
		}
	}

	execvp(argv[0], argv);
	CMD_SYSERROR("Failed to execute \"%s\"", argv[0]);
	return -1;
}
Exemple #3
0
static int lxc_attach_remount_sys_proc(void)
{
	int ret;

	ret = unshare(CLONE_NEWNS);
	if (ret < 0) {
		SYSERROR("failed to unshare mount namespace");
		return -1;
	}

	if (detect_shared_rootfs()) {
		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
			SYSERROR("Failed to make / rslave");
			ERROR("Continuing...");
		}
	}

	/* assume /proc is always mounted, so remount it */
	ret = umount2("/proc", MNT_DETACH);
	if (ret < 0) {
		SYSERROR("failed to unmount /proc");
		return -1;
	}

	ret = mount("none", "/proc", "proc", 0, NULL);
	if (ret < 0) {
		SYSERROR("failed to remount /proc");
		return -1;
	}

	/* try to umount /sys - if it's not a mount point,
	 * we'll get EINVAL, then we ignore it because it
	 * may not have been mounted in the first place
	 */
	ret = umount2("/sys", MNT_DETACH);
	if (ret < 0 && errno != EINVAL) {
		SYSERROR("failed to unmount /sys");
		return -1;
	} else if (ret == 0) {
		/* remount it */
		ret = mount("none", "/sys", "sysfs", 0, NULL);
		if (ret < 0) {
			SYSERROR("failed to remount /sys");
			return -1;
		}
	}

	return 0;
}
Exemple #4
0
/*
 * Given a lxc_storage (presumably blockdev-based), detect the fstype
 * by trying mounting (in a private mntns) it.
 * @lxc_storage: bdev to investigate
 * @type: preallocated char* in which to write the fstype
 * @len: length of passed in char*
 * Returns length of fstype, of -1 on error
 */
int detect_fs(struct lxc_storage *bdev, char *type, int len)
{
	int ret;
	int p[2];
	size_t linelen;
	pid_t pid;
	FILE *f;
	char *sp1, *sp2, *sp3;
	const char *l, *srcdev;
	char devpath[PATH_MAX];
	char *line = NULL;

	if (!bdev || !bdev->src || !bdev->dest)
		return -1;

	srcdev = lxc_storage_get_path(bdev->src, bdev->type);

	ret = pipe(p);
	if (ret < 0) {
		SYSERROR("Failed to create pipe");
		return -1;
	}

	pid = fork();
	if (pid < 0) {
		SYSERROR("Failed to fork process");
		return -1;
	}

	if (pid > 0) {
		int status;

		close(p[1]);
		memset(type, 0, len);

		ret = read(p[0], type, len - 1);
		if (ret < 0) {
			SYSERROR("Failed to read FSType from pipe");
		} else if (ret == 0) {
			ERROR("FSType not found - child exited early");
			ret = -1;
		}

		close(p[0]);
		wait(&status);

		if (ret < 0)
			return ret;

		type[len - 1] = '\0';
		INFO("Detected FSType \"%s\" for \"%s\"", type, srcdev);

		return ret;
	}

	if (unshare(CLONE_NEWNS) < 0)
		_exit(EXIT_FAILURE);

	if (detect_shared_rootfs())
		if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) {
			SYSERROR("Failed to make / rslave");
			ERROR("Continuing...");
		}

	ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
	if (ret < 0) {
		ERROR("Failed to mount \"%s\" onto \"%s\" to detect FSType", srcdev,
		      bdev->dest);
		_exit(EXIT_FAILURE);
	}

	l = linkderef(srcdev, devpath);
	if (!l)
		_exit(EXIT_FAILURE);

	f = fopen("/proc/self/mounts", "r");
	if (!f)
		_exit(EXIT_FAILURE);

	while (getline(&line, &linelen, f) != -1) {
		sp1 = strchr(line, ' ');
		if (!sp1)
			_exit(EXIT_FAILURE);

		*sp1 = '\0';
		if (strcmp(line, l))
			continue;

		sp2 = strchr(sp1 + 1, ' ');
		if (!sp2)
			_exit(EXIT_FAILURE);
		*sp2 = '\0';

		sp3 = strchr(sp2 + 1, ' ');
		if (!sp3)
			_exit(EXIT_FAILURE);
		*sp3 = '\0';

		sp2++;
		if (write(p[1], sp2, strlen(sp2)) != strlen(sp2))
			_exit(EXIT_FAILURE);

		_exit(EXIT_SUCCESS);
	}

	_exit(EXIT_FAILURE);
}
Exemple #5
0
/*
 * Given a lxc_storage (presumably blockdev-based), detect the fstype
 * by trying mounting (in a private mntns) it.
 * @lxc_storage: bdev to investigate
 * @type: preallocated char* in which to write the fstype
 * @len: length of passed in char*
 * Returns length of fstype, of -1 on error
 */
int detect_fs(struct lxc_storage *bdev, char *type, int len)
{
	int ret;
	int p[2];
	size_t linelen;
	pid_t pid;
	FILE *f;
	char *sp1, *sp2, *sp3;
	const char *l, *srcdev;
	char devpath[PATH_MAX];
	char *line = NULL;

	if (!bdev || !bdev->src || !bdev->dest)
		return -1;

	srcdev = lxc_storage_get_path(bdev->src, bdev->type);

	ret = pipe(p);
	if (ret < 0)
		return -1;

	if ((pid = fork()) < 0)
		return -1;

	if (pid > 0) {
		int status;
		close(p[1]);
		memset(type, 0, len);
		ret = read(p[0], type, len - 1);
		close(p[0]);
		if (ret < 0) {
			SYSERROR("error reading from pipe");
			wait(&status);
			return -1;
		} else if (ret == 0) {
			ERROR("child exited early - fstype not found");
			wait(&status);
			return -1;
		}
		wait(&status);
		type[len - 1] = '\0';
		INFO("detected fstype %s for %s", type, srcdev);
		return ret;
	}

	if (unshare(CLONE_NEWNS) < 0)
		exit(1);

	if (detect_shared_rootfs()) {
		if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL)) {
			SYSERROR("Failed to make / rslave");
			ERROR("Continuing...");
		}
	}

	ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
	if (ret < 0) {
		ERROR("failed mounting %s onto %s to detect fstype", srcdev,
		      bdev->dest);
		exit(1);
	}

	l = linkderef(srcdev, devpath);
	if (!l)
		exit(1);
	f = fopen("/proc/self/mounts", "r");
	if (!f)
		exit(1);

	while (getline(&line, &linelen, f) != -1) {
		sp1 = strchr(line, ' ');
		if (!sp1)
			exit(1);
		*sp1 = '\0';
		if (strcmp(line, l))
			continue;
		sp2 = strchr(sp1 + 1, ' ');
		if (!sp2)
			exit(1);
		*sp2 = '\0';
		sp3 = strchr(sp2 + 1, ' ');
		if (!sp3)
			exit(1);
		*sp3 = '\0';
		sp2++;
		if (write(p[1], sp2, strlen(sp2)) != strlen(sp2))
			exit(1);

		exit(0);
	}

	exit(1);
}