[apparmor] [PATCH 23/32] apparmor: provide the ability to boot with a default profile set on init

John Johansen john.johansen at canonical.com
Wed Jan 16 21:28:52 UTC 2013


add the ability to boot with a basic default profile instead of the
unconfined state.  This provides a way to provide total system confinement
without having to load policy in the init ramfs.

The basic default profile can be replaced during early boot to achieve
system confinement.

Signed-off-by: John Johansen <john.johansen at canonical.com>
---
 security/apparmor/Kconfig            |   11 +++++++++++
 security/apparmor/apparmorfs.c       |    4 ++++
 security/apparmor/include/apparmor.h |    1 +
 security/apparmor/include/policy.h   |    1 +
 security/apparmor/lsm.c              |   17 ++++++++++++++---
 security/apparmor/policy.c           |   21 +++++++++++++++++++++
 security/apparmor/procattr.c         |    8 +++++---
 7 files changed, 57 insertions(+), 6 deletions(-)

diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
index 9b9013b..1108be7 100644
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -29,3 +29,14 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
 	  boot.
 
 	  If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_UNCONFINED_INIT
+       bool "Set init to unconfined on boot"
+       depends on SECURITY_APPARMOR
+       default y
+       help
+         This option determines policy behavior during early boot by
+	 placing the init process in the unconfined state, or the
+	 'default' profile.
+
+	 If you are unsure how to answer this question, answer T.
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index b73e59b..1266724 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -347,6 +347,10 @@ static int __init aa_create_aafs(void)
 	if (error)
 		goto error;
 
+	if (!aa_g_unconfined_init) {
+		/* TODO: add default profile to apparmorfs */
+	}
+
 	/* TODO: add support for apparmorfs_null and apparmorfs_mnt */
 
 	/* Report that AppArmor fs is enabled */
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 8fb1488..3172801 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -41,6 +41,7 @@ extern bool aa_g_lock_policy;
 extern bool aa_g_logsyscall;
 extern bool aa_g_paranoid_load;
 extern unsigned int aa_g_path_max;
+extern bool aa_g_unconfined_init;
 
 /*
  * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 79b0d01..c3ba181 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -227,6 +227,7 @@ struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
 void aa_free_replacedby_kref(struct kref *kref);
 struct aa_profile *aa_alloc_profile(const char *name);
 struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat);
+struct aa_profile *aa_setup_default_profile(void);
 void aa_free_profile_kref(struct kref *kref);
 struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
 struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name);
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 3834890..705346d 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -741,6 +741,11 @@ module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
 static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
 module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
 
+/* Boot time to set use of default or unconfined as initial profile */
+bool aa_g_unconfined_init = CONFIG_SECURITY_APPARMOR_UNCONFINED_INIT;
+module_param_named(unconfined, aa_g_unconfined_init, bool, S_IRUSR);
+
+
 static int __init apparmor_enabled_setup(char *str)
 {
 	unsigned long enabled;
@@ -869,8 +874,6 @@ static int param_set_mode(const char *val, struct kernel_param *kp)
 
 /**
  * set_init_cxt - set a task context and profile on the first task.
- *
- * TODO: allow setting an alternate profile than unconfined
  */
 static int __init set_init_cxt(void)
 {
@@ -881,7 +884,15 @@ static int __init set_init_cxt(void)
 	if (!cxt)
 		return -ENOMEM;
 
-	cxt->profile = aa_get_profile(root_ns->unconfined);
+	if (!aa_g_unconfined_init) {
+		cxt->profile = aa_setup_default_profile();
+		if (!cxt->profile) {
+			aa_free_task_context(cxt);
+			return -ENOMEM;
+		}
+		/* fs setup of default is done in aa_create_aafs() */
+	} else
+		cxt->profile = aa_get_profile(root_ns->unconfined);
 	cred_cxt(cred) = cxt;
 
 	return 0;
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 1c22fbc..5d90b9e 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -771,6 +771,27 @@ fail:
 	return NULL;
 }
 
+/**
+ * aa_setup_default_profile - create the initial default profile
+ */
+struct aa_profile *aa_setup_default_profile(void)
+{
+	struct aa_profile *profile = aa_alloc_profile("default");
+	if (!profile)
+		return NULL;
+
+	/* the default profile pretends to be unconfined until it is replaced */
+	profile->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR;
+
+	profile->ns = aa_get_namespace(root_ns);
+
+	/* list ref */
+	aa_get_profile(profile);
+	__list_add_profile(&root_ns->base.profiles, profile);
+
+	return profile;
+}
+
 /* TODO: profile accounting - setup in remove */
 
 /**
diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
index 6c93901..39ce95a 100644
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -41,6 +41,7 @@ int aa_getprocattr(struct aa_profile *profile, char **string)
 	const char *ns_name = NULL;
 	struct aa_namespace *ns = profile->ns;
 	struct aa_namespace *current_ns = __aa_current_profile()->ns;
+	bool unconfined;
 	char *s;
 
 	if (!aa_ns_visible(current_ns, ns))
@@ -53,8 +54,9 @@ int aa_getprocattr(struct aa_profile *profile, char **string)
 	if (ns_len)
 		ns_len += 4;
 
-	/* unconfined profiles don't have a mode string appended */
-	if (!unconfined(profile))
+	/* 'unconfined' profile don't have a mode string appended */
+	unconfined = unconfined(profile) && profile == profile->ns->unconfined;
+	if (!unconfined)
 		mode_len = strlen(mode_str) + 3;	/* + 3 for _() */
 
 	name_len = strlen(profile->base.hname);
@@ -68,7 +70,7 @@ int aa_getprocattr(struct aa_profile *profile, char **string)
 		sprintf(s, ":%s://", ns_name);
 		s += ns_len;
 	}
-	if (unconfined(profile))
+	if (unconfined)
 		/* mode string not being appended */
 		sprintf(s, "%s\n", profile->base.hname);
 	else
-- 
1.7.10.4




More information about the AppArmor mailing list