[lxc-devel] [PATCH 1/1] pivot_root: switch to a new mechanism (v2)

Serge Hallyn serge.hallyn at ubuntu.com
Mon Sep 29 20:55:06 UTC 2014


Quoting Dwight Engen (dwight.engen at oracle.com):
> On Sat, 20 Sep 2014 03:15:44 +0000
> Serge Hallyn <serge.hallyn at ubuntu.com> wrote:
> 
> > This idea came from Andy Lutomirski.  Instead of using a
> > temporary directory for the pivot_root put-old, use "." both
> > for new-root and old-root.  Then fchdir into the old root
> > temporarily in order to unmount the old-root, and finally
> > chdir back into our '/'.
> > 
> > Drop lxc.pivotdir from the lxc.container.conf manpage.
> > 
> > Warn when we see a lxc.pivotdir entry (but keep it in the
> > lxc.conf for now).
> > 
> > Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
> 
> Hey Serge
> 
> Just a heads up that this change makes my containers not start on a
> 3.8.13 kernel. Reverting this change or using 3.13.11 kernel (just
> tried a newer one I had handy) works. I'll try to debug further.
> The log from trying to start a busybox container:

Fascinating.

It seems this is the case from at least v3.2 to v3.11.  

If my systemtap experiment isn't completely wrong, do_mount's
call to kern_path() for any path to mount is returning a path
with mnt->mnt_ns = NULL.  But it doesn't return an error.  So
later on, when do_loopback checks for the path's mnt_ns being
the same as current's, that fails since mnt_ns is NULL.

The easiest way to reproduce is to use the program below, call it
'pivot.c", build it, and run "sudo ./pivot", then in the resulting bash
shell try to, say, "mount --bind /mnt /mnt".

I've reached the end of my ability to system-tap, so I'm going
to build a kernel with some printk'ing :) and continue in awhile.

Note that editing the program to do pivot_root(".", "/mnt") and
umount2("/", MNT_DETACH) does NOT cause a problem.

===================================================================

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mount.h>
#include <linux/sched.h>


int main()
{
	int ret;
	ret = unshare(CLONE_NEWNS);
	if (ret)
		exit(1);
	int oldroot, newroot;

	ret = mount("/", "/mnt", "none", MS_BIND | MS_REC, NULL);
	if (ret)
		exit(1);

	oldroot = open("/", O_DIRECTORY | O_RDONLY);
	if (oldroot < 0)
		exit(1);
	newroot = open("/mnt", O_DIRECTORY | O_RDONLY);
	if (newroot < 0)
		exit(1);
	if (fchdir(newroot))
		exit(1);

	if (pivot_root(".", "."))
		exit(2);
	printf("pivoted");

	if (fchdir(oldroot) < 0)
		exit(3);
	if (umount2("/", MNT_DETACH) < 0)
		exit(3);
	if (fchdir(newroot) < 0)
		exit(4);
	printf("in new root");
	close(oldroot);
	close(newroot);
	printf("I am %d\n", getpid());
	execl("/bin/bash", "/bin/bash", NULL);
}


More information about the lxc-devel mailing list