Description: don't try apparmor transitions if aa not loaded
 If apparmor is not enabled, or the kernel doesn't support mount
 restrictions, then don't try apparmor transition.
 Also, ignore mount failures in lxc_init.  Apparmor does not
 allow lxc_init to do those mounts.
Author: Serge Hallyn <serge.hallyn@ubuntu.com>
Forwarded: no

Index: lxc-0.8.0~rc1/src/lxc/start.c
===================================================================
--- lxc-0.8.0~rc1.orig/src/lxc/start.c	2012-04-23 23:09:55.735940166 -0500
+++ lxc-0.8.0~rc1/src/lxc/start.c	2012-04-23 23:09:58.959940112 -0500
@@ -46,6 +46,8 @@
 #include <sys/poll.h>
 #include <sys/apparmor.h>
 
+int apparmor_enabled = 0;
+
 #ifdef HAVE_SYS_SIGNALFD_H
 #  include <sys/signalfd.h>
 #else
@@ -506,6 +508,38 @@
 }
 #endif
 
+#define AA_DEF_PROFILE "lxc-container-default"
+static int apparmor_load(struct lxc_handler *handler)
+{
+	if (!apparmor_enabled) {
+		INFO("apparmor not enabled");
+		return 0;
+	}
+
+	if (!handler->conf->aa_profile)
+		handler->conf->aa_profile = AA_DEF_PROFILE;
+
+	if (strcmp(handler->conf->aa_profile, "unconfined") == 0 &&
+	    aa_am_unconfined()) {
+		INFO("apparmor profile unchanged");
+		return 0;
+	}
+
+	/* aa_change_onexec makes more sense since we want to transition when
+	 * /sbin/init is exec'd.  But the transitions doesn't seem to work
+	 * then (refused).  aa_change_onexec will work since we're doing it
+	 * right before the exec, so we'll just use that for now.
+	 */
+	//if (aa_change_onexec(handler->conf->aa_profile) < 0) {
+	if (aa_change_profile(handler->conf->aa_profile) < 0) {
+		SYSERROR("failed to change apparmor profile to %s", handler->conf->aa_profile);
+		return -1;
+	}
+	INFO("changed apparmor profile to %s", handler->conf->aa_profile);
+
+	return 0;
+}
+
 static int do_start(void *data)
 {
 	struct lxc_handler *handler = data;
@@ -550,30 +584,8 @@
 
 	close(handler->sigfd);
 
-#define AA_DEF_PROFILE "lxc-container-default"
-
-	if (!handler->conf->aa_profile)
-		handler->conf->aa_profile = AA_DEF_PROFILE;
-
-	if (strcmp(handler->conf->aa_profile, "unconfined") == 0 &&
-	    aa_am_unconfined()) {
-		INFO("apparmor profile unchanged");
-		goto skip_profile;
-	}
-
-	/* aa_change_onexec makes more sense since we want to transition when
-	 * /sbin/init is exec'd.  But the transitions doesn't seem to work
-	 * then (refused).  aa_change_onexec will work since we're doing it
-	 * right before the exec, so we'll just use that for now.
-	 */
-	//if (aa_change_onexec(handler->conf->aa_profile) < 0) {
-	if (aa_change_profile(handler->conf->aa_profile) < 0) {
-		SYSERROR("failed to change apparmor profile to %s", handler->conf->aa_profile);
+	if (apparmor_load(handler) < 0)
 		return -1;
-	}
-	INFO("changed apparmor profile to %s", handler->conf->aa_profile);
-
-skip_profile:
 
 	/* after this call, we are in error because this
 	 * ops should not return as it execs */
@@ -786,12 +798,36 @@
 	.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;
 
Index: lxc-0.8.0~rc1/src/lxc/lxc_init.c
===================================================================
--- lxc-0.8.0~rc1.orig/src/lxc/lxc_init.c	2012-04-23 23:09:13.935940874 -0500
+++ lxc-0.8.0~rc1/src/lxc/lxc_init.c	2012-04-23 23:09:58.963940112 -0500
@@ -126,7 +126,7 @@
 	}
 
 	if (lxc_setup_fs())
-		exit(err);
+		INFO("Ignoring error in setting up fs");
 
 	if (lxc_caps_reset())
 		exit(err);
