This is an alternative to the pivot_root patch which I just
sent. It has the advantage of being much simpler. It also
won't have a problem with the container's / being a read-only
mount. It has the disadvantage, of course, of being escapable.
From a91bca7f60f27e8fbdb4e3bacf3232a6cbb630d3 Mon Sep 17 00:00:00 2001
From: root <root(a)localhost.localdomain>
Date: Fri, 3 Apr 2009 23:35:24 -0400
Subject: [PATCH 1/1] lxc: use chroot instead of pivot_root
pivot_root is too fragile. For instance, if the container's
/ is read-only, we can't create .oldroot. Maybe we're happy
telling users that if they can't create .oldroot at container
create time, then they must make sure it exists ahead of time.
Or, maybe we're ok with chroot being escapable, and should
just go this simple route.
Signed-off-by: Serge Hallyn <serue(a)us.ibm.com>
---
src/lxc_container.c | 75 +++++++++++++--------------------------------------
1 files changed, 19 insertions(+), 56 deletions(-)
diff --git a/src/lxc_container.c b/src/lxc_container.c
index 3f17b8d..142ed4d 100644
--- a/src/lxc_container.c
+++ b/src/lxc_container.c
@@ -264,52 +264,6 @@ static int lxcContainerChildMountSort(const void *a, const void *b)
return strcmp(*sb, *sa);
}
-static int lxcContainerPivotRoot(virDomainFSDefPtr root)
-{
- int rc;
- char *oldroot;
-
- /* First step is to ensure the new root itself is
- a mount point */
- if (mount(root->src, root->src, NULL, MS_BIND, NULL) < 0) {
- virReportSystemError(NULL, errno,
- _("failed to bind new root %s"),
- root->src);
- return -1;
- }
-
- if (virAsprintf(&oldroot, "%s/.oldroot", root->src) < 0) {
- virReportOOMError(NULL);
- return -1;
- }
-
- if ((rc = virFileMakePath(oldroot)) < 0) {
- virReportSystemError(NULL, rc,
- _("failed to create %s"),
- oldroot);
- VIR_FREE(oldroot);
- return -1;
- }
-
- /* The old root directory will live at /.oldroot after
- * this and will soon be unmounted completely */
- if (pivot_root(root->src, oldroot) < 0) {
- virReportSystemError(NULL, errno,
- _("failed to pivot root %s to %s"),
- oldroot, root->src);
- VIR_FREE(oldroot);
- return -1;
- }
- VIR_FREE(oldroot);
-
- /* CWD is undefined after pivot_root, so go to / */
- if (chdir("/") < 0) {
- return -1;
- }
-
- return 0;
-}
-
static int lxcContainerPopulateDevices(void)
{
int i;
@@ -349,10 +303,9 @@ static int lxcContainerPopulateDevices(void)
_("cannot create /dev/pts"));
return -1;
}
- if (mount("/.oldroot/dev/pts", "/dev/pts", NULL,
- MS_MOVE, NULL) < 0) {
+ if (mount("devpts", "/dev/pts", "devpts", 0, NULL) <
0) {
virReportSystemError(NULL, errno, "%s",
- _("failed to move /dev/pts into container"));
+ _("failed to mount /dev/pts in container"));
return -1;
}
@@ -461,15 +414,25 @@ static int lxcContainerUnmountOldFS(void)
}
-/* Got a FS mapped to /, we're going the pivot_root
- * approach to do a better-chroot-than-chroot
- * this is based on this thread
http://lkml.org/lkml/2008/3/5/29
- */
-static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
+/* Got a FS mapped to /, now chroot.
+ * pivot_root would work, but requires too much hand-holding
+ * (especially, old_root->parent must not be shared) */
+static int lxcContainerSetupChroot(virDomainDefPtr vmDef,
virDomainFSDefPtr root)
{
- if (lxcContainerPivotRoot(root) < 0)
+ if (chdir(root->src) < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to chdir to %s"),
+ root->src);
+ return -1;
+ }
+
+ if (chroot(root->src) < 0) {
+ virReportSystemError(NULL, errno,
+ _("failed to chroot to %s"),
+ root->src);
return -1;
+ }
if (virFileMakePath("/proc") < 0 ||
mount("none", "/proc", "proc", 0, NULL) < 0) {
@@ -537,7 +500,7 @@ static int lxcContainerSetupMounts(virDomainDefPtr vmDef)
}
if (root)
- return lxcContainerSetupPivotRoot(vmDef, root);
+ return lxcContainerSetupChroot(vmDef, root);
else
return lxcContainerSetupExtraMounts(vmDef);
}
--
1.6.2