- Add apparmorfs features file (may break this into a directory, sysfs style)

- do split init so apparmor is initialized in security_initcall
This commit is contained in:
John Johansen 2008-01-10 18:05:50 +00:00
parent fb62cb15b2
commit 46fefd63a1
5 changed files with 254 additions and 0 deletions

View file

@ -0,0 +1,47 @@
---
security/apparmor/apparmorfs.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -99,6 +99,22 @@ static struct file_operations apparmorfs
.read = aa_matching_read,
};
+/* apparmor/features */
+static ssize_t aa_features_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char *features = "file=3.0 capability=1.0 network=1.0 "
+ "change_hat=1.3 change_profile=1.0 "
+ "aanamespaces=1.0";
+
+ return simple_read_from_buffer(buf, size, ppos, features,
+ strlen(features));
+}
+
+static struct file_operations apparmorfs_features_fops = {
+ .read = aa_features_read,
+};
+
/* apparmor/.load */
static ssize_t aa_profile_load(struct file *f, const char __user *buf,
size_t size, loff_t *pos)
@@ -204,6 +220,7 @@ void destroy_apparmorfs(void)
aafs_remove(".replace");
aafs_remove(".load");
aafs_remove("matching");
+ aafs_remove("features");
aafs_remove("profiles");
securityfs_remove(apparmor_dentry);
apparmor_dentry = NULL;
@@ -232,6 +249,9 @@ int create_apparmorfs(void)
error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
if (error)
goto error;
+ error = aafs_create("features", 0444, &apparmorfs_features_fops);
+ if (error)
+ goto error;
error = aafs_create(".load", 0640, &apparmorfs_profile_load);
if (error)
goto error;

View file

@ -28,6 +28,7 @@ difficult to implement open-unlink-fstat semantics correctly in the
client, without having this information.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: John Johansen <jjohansen@suse.de>
---
---

View file

@ -14,6 +14,7 @@ separate file operation for this, so remove ia_file, ATTR_FILE and
convert existing users: fuse and AFS.
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> ---
Signed-off-by: John Johansen <jjohansen@suse.de> ---
---
fs/afs/dir.c | 1 +

View file

@ -84,3 +84,6 @@ apparmor-security-goal.diff
# vfs_rmdir-args.diff
# vfs_unlink-args.diff
# may_delete-args.diff
apparmor-matching-string.diff
apparmor-features.diff
split_init.diff

View file

@ -0,0 +1,202 @@
---
security/apparmor/Kconfig | 15 ++++++
security/apparmor/apparmorfs.c | 12 +++++
security/apparmor/lsm.c | 93 +++++++++++++++++++++++++++++++++--------
3 files changed, 103 insertions(+), 17 deletions(-)
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -25,3 +25,18 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
bootup.
If you are unsure how to answer this question, answer 1.
+
+config SECURITY_APPARMOR_DISABLE
+ bool "AppArmor runtime disable"
+ depends on SECURITY_APPARMOR
+ default n
+ help
+ This option enables writing to a apparmorfs node 'disable', which
+ allows AppArmor to be disabled at runtime prior to the policy load.
+ AppArmor will then remain disabled until the next boot.
+ This option is similar to the apparmor.enabled=0 boot parameter,
+ but is to support runtime disabling of AppArmor, e.g. from
+ /sbin/init, for portability across platforms where boot
+ parameters are difficult to employ.
+
+ If you are unsure how to answer this question, answer N.
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -231,6 +231,9 @@ int create_apparmorfs(void)
{
int error;
+ if (!apparmor_initialized)
+ return 0;
+
if (apparmor_dentry) {
AA_ERROR("%s: AppArmor securityfs already exists\n",
__FUNCTION__);
@@ -262,11 +265,20 @@ int create_apparmorfs(void)
if (error)
goto error;
+ /* Report that AppArmor has been successfully initialized */
+ if (apparmor_complain)
+ info_message("AppArmor initialized: complainmode enabled");
+ else
+ info_message("AppArmor initialized");
+
return 0;
error:
destroy_apparmorfs();
AA_ERROR("Error creating AppArmor securityfs\n");
+ apparmor_disable();
return error;
}
+fs_initcall(create_apparmorfs);
+
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -23,16 +23,8 @@
#include "apparmor.h"
#include "inline.h"
-/* Boot time disable flag */
-int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
-
-static int __init apparmor_enabled_setup(char *str)
-{
- apparmor_enabled = simple_strtol(str, NULL, 0);
- return 1;
-}
-__setup("apparmor=", apparmor_enabled_setup);
-
+/* Flag indicating whether initialization completed */
+int apparmor_initialized = 0;
static int param_set_aabool(const char *val, struct kernel_param *kp);
static int param_get_aabool(char *buffer, struct kernel_param *kp);
@@ -75,6 +67,19 @@ unsigned int apparmor_path_max = 2 * PAT
module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
+/* Boot time disable flag */
+#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
+#define AA_ENABLED_PERMS 0600
+#else
+#define AA_ENABLED_PERMS 0400
+#endif
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
+unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
+ &apparmor_enabled, AA_ENABLED_PERMS);
+MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
+
+
static int param_set_aabool(const char *val, struct kernel_param *kp)
{
if (aa_task_context(current))
@@ -103,6 +108,34 @@ static int param_get_aauint(char *buffer
return param_get_uint(buffer, kp);
}
+static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
+{
+ char *endp;
+ unsigned long l;
+
+ if (!apparmor_initialized) {
+ apparmor_enabled = 0;
+ return 0;
+ }
+
+ if (aa_task_context(current))
+ return -EPERM;
+
+ if (!apparmor_enabled)
+ return -EINVAL;
+
+ if (!val)
+ return -EINVAL;
+
+ l = simple_strtoul(val, &endp, 0);
+ if (endp == val || l != 0)
+ return -EINVAL;
+
+ apparmor_enabled = 0;
+ apparmor_disable();
+ return 0;
+}
+
static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
const char *name)
{
@@ -879,13 +912,13 @@ struct security_operations apparmor_ops
.socket_shutdown = apparmor_socket_shutdown,
};
-static void info_message(const char *str)
+void info_message(const char *str)
{
struct aa_audit sa;
memset(&sa, 0, sizeof(sa));
sa.gfp_mask = GFP_KERNEL;
sa.info = str;
- printk(KERN_INFO "AppArmor: %s", str);
+ printk(KERN_INFO "AppArmor: %s\n", str);
aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
}
@@ -913,10 +946,12 @@ static int __init apparmor_init(void)
goto register_security_out;
}
- if (apparmor_complain)
- info_message("AppArmor initialized: complainmode enabled");
- else
- info_message("AppArmor initialized");
+ /* Report that AppArmor successfully registered but delay
+ * reporting on success/failure of initialization until apparmorfs
+ * is created
+ */
+ apparmor_initialized = 1;
+ info_message("AppArmor registered");
return error;
@@ -931,7 +966,31 @@ createfs_out:
}
-module_init(apparmor_init);
+security_initcall(apparmor_init);
+
+void apparmor_disable(void)
+{
+ /* Remove and release all the profiles on the profile list. */
+ mutex_lock(&aa_interface_lock);
+ aa_profile_ns_list_release();
+
+ /* FIXME: cleanup profiles references on files */
+ free_default_namespace();
+
+ /*
+ * Delay for an rcu cycle to make sure that all active task
+ * context readers have finished, and all profiles have been
+ * freed by their rcu callbacks.
+ */
+ synchronize_rcu();
+
+ destroy_apparmorfs();
+ mutex_unlock(&aa_interface_lock);
+
+ apparmor_initialized = 0;
+
+ info_message("AppArmor protection removed");
+}
MODULE_DESCRIPTION("AppArmor process confinement");
MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");