Description: umount proc if it isn't ours
 If /proc is already mounted, make sure that /proc/self points to 1,
 since we are container init.  Otherwise, assume proc is an old one, and
 umount it and remount our own.  If we keep the old proc mounted,
 apparmor transitions will by tried for wrong task and fail.
 Also move the check for whether apparmor is enabled to inside __lxc_start()
 so that lxc-execute can use it.
 This won't be forwarded as it's part of the apparmorization which is
 not yet upstream.
Author: Serge Hallyn <serge.hallyn@ubuntu.com>
Forwarded: no
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/993706

Index: lxc-0.8.0~rc1/src/lxc/conf.c
===================================================================
--- lxc-0.8.0~rc1.orig/src/lxc/conf.c	2012-05-07 21:35:36.758139051 +0000
+++ lxc-0.8.0~rc1/src/lxc/conf.c	2012-05-07 21:40:34.470135873 +0000
@@ -2115,28 +2115,38 @@
 }
 
 /*
- * make sure /proc/1 exists, else mount /proc.  Return 0 if proc was
+ * make sure /proc/self exists, and points to '1', since we are the
+ * container init.
+ * Else mount /proc.  Return 0 if proc was
  * already mounted, 1 if we mounted it, -1 if we failed.
  */
-static int mount_proc_if_needed(char *rootfs_tgt)
+static int mount_proc_if_needed(char *root_src, char *rootfs_tgt)
 {
-	struct stat statbuf;
 	char path[MAXPATHLEN];
-	int ret;
+	char link[20];
+	int linklen, ret;
 
-	ret = snprintf(path, MAXPATHLEN, "%s/proc/1/cmdline", rootfs_tgt);
+	ret = snprintf(path, MAXPATHLEN, "%s/proc/self", root_src ? rootfs_tgt : "");
 	if (ret < 0 || ret >= MAXPATHLEN) {
 		SYSERROR("proc path name too long");
 		return -1;
 	}
-	ret = stat(path, &statbuf);
-	INFO("checking if proc mount needed\n");
-	if (ret == 0) {
-		INFO("no proc mount needed\n");
-		return 0;
+	memset(link, 0, 20);
+	linklen = readlink(path, link, 20);
+	INFO("I am %d, /proc/self points to %s\n", getpid(), link);
+	ret = snprintf(path, MAXPATHLEN, "%s/proc", root_src ? rootfs_tgt : "");
+	if (linklen < 0) /* /proc not mounted */
+		goto domount;
+	/* can't be longer than rootfs/proc/1 */
+	if (strncmp(link, "1", linklen) != 0) {
+		/* wrong /procs mounted */
+		umount2(path, MNT_DETACH); /* ignore failure */
+		goto domount;
 	}
-	ret = snprintf(path, MAXPATHLEN, "%s/proc", rootfs_tgt);
-	INFO("proc mount needed, mounting to %s\n", path);
+	/* the right proc is already mounted */
+	return 0;
+
+domount:
 	if (mount("proc", path, "proc", 0, NULL))
 		return -1;
 	INFO("Mounted /proc for the container\n");
@@ -2192,15 +2202,11 @@
 	 * then (refused).  aa_change_onexec will work since we're doing it
 	 * right before the exec, so we'll just use that for now.
 	 * In case the container fstab didn't mount /proc, we mount it.
-	 *
-	 * But if there is no rootfs, then don't try to mount it.
 	 */
 	INFO("rootfs path is .%s., mount is .%s.", lxc_conf->rootfs.path,
 		lxc_conf->rootfs.mount);
-	if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0)
-		mounted = 0;
-	else
-		mounted = mount_proc_if_needed(lxc_conf->rootfs.mount);
+
+	mounted = mount_proc_if_needed(lxc_conf->rootfs.path, lxc_conf->rootfs.mount);
 	if (mounted == -1) {
 		SYSERROR("failed to mount /proc in the container.");
 		return -1;
Index: lxc-0.8.0~rc1/src/lxc/start.c
===================================================================
--- lxc-0.8.0~rc1.orig/src/lxc/start.c	2012-05-07 21:35:36.646139051 +0000
+++ lxc-0.8.0~rc1/src/lxc/start.c	2012-05-07 21:42:12.506139286 +0000
@@ -511,8 +511,6 @@
 #define AA_DEF_PROFILE "lxc-container-default"
 static int apparmor_load(struct lxc_handler *handler)
 {
-	int mounted;
-
 	if (!apparmor_enabled) {
 		INFO("apparmor not enabled");
 		return 0;
@@ -700,6 +698,28 @@
 	return -1;
 }
 
+#define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask"
+#define AA_ENABLED_FILE "/sys/module/apparmor/parameters/enabled"
+static int check_apparmor_enabled(void)
+{
+	struct stat statbuf;
+	FILE *fin;
+	char e;
+	int ret;
+
+	ret = stat(AA_MOUNT_RESTR, &statbuf);
+	if (ret != 0)
+		return 0;
+	fin = fopen(AA_ENABLED_FILE, "r");
+	if (!fin)
+		return 0;
+	ret = fscanf(fin, "%c", &e);
+	fclose(fin);
+	if (ret == 1 && e == 'Y')
+		return 1;
+	return 0;
+}
+
 int __lxc_start(const char *name, struct lxc_conf *conf,
 		struct lxc_operations* ops, void *data)
 {
@@ -707,6 +727,8 @@
 	int err = -1;
 	int status;
 
+	apparmor_enabled = check_apparmor_enabled();
+
 	handler = lxc_init(name, conf);
 	if (!handler) {
 		ERROR("failed to initialize the container");
@@ -798,36 +820,12 @@
 	.post_start = post_start
 };
 
-#define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask"
-#define AA_ENABLED_FILE "/sys/module/apparmor/parameters/enabled"
-static int check_apparmor_enabled(void)
-{
-	struct stat statbuf;
-	FILE *fin;
-	char e;
-	int ret;
-
-	ret = stat(AA_MOUNT_RESTR, &statbuf);
-	if (ret != 0)
-		return 0;
-	fin = fopen(AA_ENABLED_FILE, "r");
-	if (!fin)
-		return 0;
-	fscanf(fin, "%c", &e);
-	fclose(fin);
-	if (e == 'Y')
-		return 1;
-	return 0;
-}
-
 int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf)
 {
 	struct start_args start_arg = {
 		.argv = argv,
 	};
 
-	apparmor_enabled = check_apparmor_enabled();
-
 	if (lxc_check_inherited(conf, -1))
 		return -1;
 
