DB> +#if 0 DB> + ttyfd = open(argv->ttyPath, O_RDWR|O_NOCTTY); DB> + if (ttyfd < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("open(%s) failed: %s"), argv->ttyPath, strerror(errno)); DB> + return -1; DB> + } DB> +#endif Should this bit be removed? DB> + if (root) { DB> + char *oldroot; DB> + struct mntent *mntent; DB> + char **mounts = NULL; DB> + int nmounts = 0; DB> + FILE *procmnt; DB> + const struct { DB> + int maj; DB> + int min; DB> + mode_t mode; DB> + const char *path; DB> + } devs[] = { DB> + { 1, 3, 0666, "/dev/null" }, DB> + { 1, 5, 0666, "/dev/zero" }, DB> + { 1, 7, 0666, "/dev/full" }, DB> + { 5, 1, 0600, "/dev/console" }, DB> + { 1, 8, 0666, "/dev/random" }, DB> + { 1, 9, 0666, "/dev/urandom" }, DB> + }; DB> + DB> + /* Got a FS mapped to /, we're going the pivot_root DB> + approach to do a better-chroot-than-chroot */ DB> + DB> + /* this is based on this thread http://lkml.org/lkml/2008/3/5/29 */ DB> + DB> + /* First step is to ensure the new root itself is DB> + a mount point */ DB> + if (mount(root->src, root->src, NULL, MS_BIND, NULL) < 0) { DB> lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> - _("failed to mount %s at %s for container: %s"), DB> - curMount->src, curMount->dst, strerror(errno)); DB> + _("failed to bind new root %s: %s"), DB> + root->src, strerror(errno)); DB> + return -1; DB> + } DB> + DB> + if (asprintf(&oldroot, "%s/.oldroot", root->src) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_NO_MEMORY, NULL); DB> + return -1; DB> + } DB> + DB> + if (virFileMakePath(oldroot) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to create %s: %s"), DB> + oldroot, strerror(errno)); DB> + return -1; DB> + } DB> + DB> + /* The old root directory will live at /.oldroot after DB> + * this and will soon be unmounted completely */ DB> + if (pivot_root(root->src, oldroot) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to pivot root %s to %s: %s"), DB> + oldroot, root->src, strerror(errno)); DB> + return -1; DB> + } DB> + DB> + /* CWD is undefined after pivot_root, so go to / */ DB> + if (chdir("/") < 0) { DB> + return -1; DB> + } DB> + DB> + if (virFileMakePath("/proc") < 0 || DB> + mount("none", "/proc", "proc", 0, NULL) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to mount /proc for container: %s"), DB> + strerror(errno)); DB> + return -1; DB> + } DB> + if (virFileMakePath("/dev") < 0 || DB> + mount("none", "/dev", "tmpfs", 0, NULL) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to mount /dev tmpfs for container: %s"), DB> + strerror(errno)); DB> + return -1; DB> + } DB> + /* Move old devpts into container, since we have to DB> + connect to the master ptmx which was opened in DB> + the parent. DB> + XXX This sucks, we need to figure out how to get our DB> + own private devpts for isolation DB> + */ DB> + if (virFileMakePath("/dev/pts") < 0 || DB> + mount("/.oldroot/dev/pts", "/dev/pts", NULL, DB> + MS_MOVE, NULL) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to move /dev/pts into container: %s"), DB> + strerror(errno)); DB> + return -1; DB> + } DB> + DB> + /* Populate /dev/ with a few important bits */ DB> + for (i = 0 ; i < ARRAY_CARDINALITY(devs) ; i++) { DB> + dev_t dev = makedev(devs[i].maj, devs[i].min); DB> + if (mknod(devs[i].path, 0, dev) < 0 || DB> + chmod(devs[i].path, devs[i].mode)) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to make device %s: %s"), DB> + devs[i].path, strerror(errno)); DB> + return -1; DB> + } DB> + } DB> + DB> + /* Pull in rest of container's mounts */ DB> + for (tmp = vmDef->fss; tmp; tmp = tmp->next) { DB> + char *src; DB> + if (STREQ(tmp->dst, "/")) DB> + continue; DB> + // XXX fix DB> + if (tmp->type != VIR_DOMAIN_FS_TYPE_MOUNT) DB> + continue; DB> + DB> + if (asprintf(&src, "/.oldroot/%s", tmp->src) < 0) DB> + return -1; DB> + DB> + if (virFileMakePath(tmp->dst) < 0 || DB> + mount(src, tmp->dst, NULL, MS_BIND, NULL) < 0) { DB> + VIR_FREE(src); DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to mount %s at %s for container: %s"), DB> + tmp->src, tmp->dst, strerror(errno)); DB> + return -1; DB> + } DB> + VIR_FREE(src); DB> + } DB> + DB> + if (!(procmnt = setmntent("/proc/mounts", "r"))) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to read /proc/mounts: %s"), DB> + strerror(errno)); DB> + return -1; DB> + } DB> + while ((mntent = getmntent(procmnt)) != NULL) { DB> + if (!STRPREFIX(mntent->mnt_dir, "/.oldroot")) DB> + continue; DB> + if (VIR_REALLOC_N(mounts, nmounts+1) < 0) { DB> + endmntent(procmnt); DB> + return -1; DB> + } DB> + if (!(mounts[nmounts++] = strdup(mntent->mnt_dir))) { DB> + endmntent(procmnt); DB> + return -1; DB> + } DB> + } DB> + endmntent(procmnt); DB> + DB> + qsort(mounts, nmounts, sizeof(mounts[0]), DB> + lxcContainerChildMountSort); DB> + DB> + for (i = 0 ; i < nmounts ; i++) { DB> + if (umount(mounts[i]) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to unmount %s: %s"), DB> + mounts[i], strerror(errno)); DB> + return -1; DB> + } DB> + VIR_FREE(mounts[i]); DB> + } DB> + VIR_FREE(mounts); I'd really like to see this mondo if block broken out into at least an lxcPivotRoot() function, if not further. This is pretty long and hairy, IMHO. DB> + } else { DB> + /* Nothing mapped to /, we're using the main root, DB> + but with extra stuff mapped in */ DB> + for (tmp = vmDef->fss; tmp; tmp = tmp->next) { DB> + // XXX fix DB> + if (tmp->type != VIR_DOMAIN_FS_TYPE_MOUNT) DB> + continue; DB> + rc = mount(tmp->src, DB> + tmp->dst, DB> + NULL, DB> + MS_BIND, DB> + NULL); DB> + if (0 != rc) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to mount %s at %s for container: %s"), DB> + tmp->src, tmp->dst, strerror(errno)); DB> + return -1; DB> + } DB> + } DB> + DB> + /* mount /proc */ DB> + if (mount("lxcproc", "/proc", "proc", 0, NULL) < 0) { DB> + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, DB> + _("failed to mount /proc for container: %s"), DB> + strerror(errno)); DB> return -1; DB> } DB> } Can we do the same mount of /proc no matter which option we take above? It seems like after the root has been pivoted (or not), we can do the same mount of proc, no? It seems like all of the above could/should be in an lxcContainerDoMounts() function or something, just like the lxcContainerSetStdio() function that gets called a bit later. The added functionality is excellent, by the way :) Thanks! -- Dan Smith IBM Linux Technology Center Open Hypervisor Team email: danms@xxxxxxxxxx
Attachment:
pgp0J9oRGDcjS.pgp
Description: PGP signature
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list