From a86b6215a74b1feb2667204e214fbfd2f7decc5c Mon Sep 17 00:00:00 2001
From: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
Date: Mon, 14 Jul 2014 18:01:51 +0800
Subject: [PATCH] LXC: create a bind mount for sysfs when enable userns but
 disable netns

kernel commit 7dc5dbc879bd0779924b5132a48b731a0bc04a1e
forbid us doing a fresh mount for sysfs
when enable userns but disable netns.
This patch will create a bind mount in this senario.

Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com>
---
 src/lxc/lxc_container.c | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

Index: libvirt-1.2.5/src/lxc/lxc_container.c
===================================================================
--- libvirt-1.2.5.orig/src/lxc/lxc_container.c
+++ libvirt-1.2.5/src/lxc/lxc_container.c
@@ -815,10 +815,13 @@ static int lxcContainerSetReadOnly(void)
 }
 
 
-static int lxcContainerMountBasicFS(bool userns_enabled)
+static int lxcContainerMountBasicFS(bool userns_enabled,
+                                    bool netns_disabled)
 {
     size_t i;
     int rc = -1;
+    char* mnt_src = NULL;
+    int mnt_mflags;
 
     VIR_DEBUG("Mounting basic filesystems");
 
@@ -826,8 +829,25 @@ static int lxcContainerMountBasicFS(bool
         bool bindOverReadonly;
         virLXCBasicMountInfo const *mnt = &lxcBasicMounts[i];
 
+        /* When enable userns but disable netns, kernel will
+         * forbid us doing a new fresh mount for sysfs.
+         * So we had to do a bind mount for sysfs instead.
+         */
+        if (userns_enabled && netns_disabled &&
+            STREQ(mnt->src, "sysfs")) {
+            if (VIR_STRDUP(mnt_src, "/sys") < 0) {
+                goto cleanup;
+            }
+            mnt_mflags = MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY|MS_BIND;
+        } else {
+            if (VIR_STRDUP(mnt_src, mnt->src) < 0) {
+                goto cleanup;
+            }
+            mnt_mflags = mnt->mflags;
+        }
+
         VIR_DEBUG("Processing %s -> %s",
-                  mnt->src, mnt->dst);
+                  mnt_src, mnt->dst);
 
         if (mnt->skipUnmounted) {
             char *hostdir;
@@ -856,7 +876,7 @@ static int lxcContainerMountBasicFS(bool
         if (virFileMakePath(mnt->dst) < 0) {
             virReportSystemError(errno,
                                  _("Failed to mkdir %s"),
-                                 mnt->src);
+                                 mnt_src);
             goto cleanup;
         }
 
@@ -867,24 +887,24 @@ static int lxcContainerMountBasicFS(bool
          * we mount the filesystem in read-write mode initially, and then do a
          * separate read-only bind mount on top of that.
          */
-        bindOverReadonly = !!(mnt->mflags & MS_RDONLY);
+        bindOverReadonly = !!(mnt_mflags & MS_RDONLY);
 
         VIR_DEBUG("Mount %s on %s type=%s flags=%x",
-                  mnt->src, mnt->dst, mnt->type, mnt->mflags & ~MS_RDONLY);
-        if (mount(mnt->src, mnt->dst, mnt->type, mnt->mflags & ~MS_RDONLY, NULL) < 0) {
+                  mnt_src, mnt->dst, mnt->type, mnt_mflags & ~MS_RDONLY);
+        if (mount(mnt_src, mnt->dst, mnt->type, mnt_mflags & ~MS_RDONLY, NULL) < 0) {
             virReportSystemError(errno,
                                  _("Failed to mount %s on %s type %s flags=%x"),
-                                 mnt->src, mnt->dst, NULLSTR(mnt->type),
-                                 mnt->mflags & ~MS_RDONLY);
+                                 mnt_src, mnt->dst, NULLSTR(mnt->type),
+                                 mnt_mflags & ~MS_RDONLY);
             goto cleanup;
         }
 
         if (bindOverReadonly &&
-            mount(mnt->src, mnt->dst, NULL,
+            mount(mnt_src, mnt->dst, NULL,
                   MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
             virReportSystemError(errno,
                                  _("Failed to re-mount %s on %s flags=%x"),
-                                 mnt->src, mnt->dst,
+                                 mnt_src, mnt->dst,
                                  MS_BIND|MS_REMOUNT|MS_RDONLY);
             goto cleanup;
         }
@@ -893,6 +913,7 @@ static int lxcContainerMountBasicFS(bool
     rc = 0;
 
  cleanup:
+    VIR_FREE(mnt_src);
     VIR_DEBUG("rc=%d", rc);
     return rc;
 }
@@ -1643,7 +1664,8 @@ static int lxcContainerSetupPivotRoot(vi
         goto cleanup;
 
     /* Mounts the core /proc, /sys, etc filesystems */
-    if (lxcContainerMountBasicFS(vmDef->idmap.nuidmap) < 0)
+    if (lxcContainerMountBasicFS(vmDef->idmap.nuidmap,
+                                 !vmDef->nnets) < 0)
         goto cleanup;
 
     /* Ensure entire root filesystem (except /.oldroot) is readonly */
