mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-05 00:35:13 +00:00
231 lines
6.4 KiB
Diff
231 lines
6.4 KiB
Diff
---
|
|
security/apparmor/Kconfig | 15 +++++
|
|
security/apparmor/apparmor.h | 5 +
|
|
security/apparmor/apparmorfs.c | 8 ++
|
|
security/apparmor/lsm.c | 110 +++++++++++++++++++++++++++++++++++------
|
|
4 files changed, 124 insertions(+), 14 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/apparmor.h
|
|
+++ b/security/apparmor/apparmor.h
|
|
@@ -231,6 +231,11 @@ extern int aa_net_perm(struct aa_profile
|
|
int family, int type, int protocol);
|
|
extern int aa_revalidate_sk(struct sock *sk, char *operation);
|
|
|
|
+/* lsm.c */
|
|
+extern int apparmor_initialized;
|
|
+extern void info_message(const char *str);
|
|
+extern void apparmor_disable(void);
|
|
+
|
|
/* list.c */
|
|
extern void aa_profilelist_release(void);
|
|
|
|
--- a/security/apparmor/apparmorfs.c
|
|
+++ b/security/apparmor/apparmorfs.c
|
|
@@ -214,6 +214,9 @@ int create_apparmorfs(void)
|
|
{
|
|
int error;
|
|
|
|
+ if (!apparmor_initialized)
|
|
+ return 0;
|
|
+
|
|
if (apparmor_dentry) {
|
|
AA_ERROR("%s: AppArmor securityfs already exists\n",
|
|
__FUNCTION__);
|
|
@@ -242,11 +245,16 @@ int create_apparmorfs(void)
|
|
if (error)
|
|
goto error;
|
|
|
|
+ /* Report that AppArmor fs is enabled */
|
|
+ info_message("AppArmor Filesystem Enabled");
|
|
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,25 @@ 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 __init apparmor_enabled_setup(char *str)
|
|
+{
|
|
+ apparmor_enabled = simple_strtol(str, NULL, 0);
|
|
+ return 1;
|
|
+}
|
|
+__setup("apparmor=", apparmor_enabled_setup);
|
|
+
|
|
static int param_set_aabool(const char *val, struct kernel_param *kp)
|
|
{
|
|
if (aa_task_context(current))
|
|
@@ -103,6 +114,35 @@ static int param_get_aauint(char *buffer
|
|
return param_get_uint(buffer, kp);
|
|
}
|
|
|
|
+/* allow run time disabling of apparmor */
|
|
+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 (!apparmor_enabled)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (aa_task_context(current))
|
|
+ return -EPERM;
|
|
+
|
|
+ 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)
|
|
{
|
|
@@ -880,14 +920,15 @@ 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);
|
|
- aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
|
|
+ printk(KERN_INFO "AppArmor: %s\n", str);
|
|
+ if (audit_enabled)
|
|
+ aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
|
|
}
|
|
|
|
static int __init apparmor_init(void)
|
|
@@ -914,6 +955,8 @@ static int __init apparmor_init(void)
|
|
goto register_security_out;
|
|
}
|
|
|
|
+ /* Report that AppArmor successfully initialized */
|
|
+ apparmor_initialized = 1;
|
|
if (apparmor_complain)
|
|
info_message("AppArmor initialized: complainmode enabled");
|
|
else
|
|
@@ -932,7 +975,46 @@ 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);
|
|
+ write_lock(&profile_list_lock);
|
|
+ while (!list_empty(&profile_list)) {
|
|
+ struct aa_profile *profile =
|
|
+ list_entry(profile_list.next, struct aa_profile, list);
|
|
+
|
|
+ /* Remove the profile from each task context it is on. */
|
|
+ lock_profile(profile);
|
|
+ profile->isstale = 1;
|
|
+ aa_unconfine_tasks(profile);
|
|
+ unlock_profile(profile);
|
|
+
|
|
+ /* Release the profile itself. */
|
|
+ list_del_init(&profile->list);
|
|
+ aa_put_profile(profile);
|
|
+ }
|
|
+ write_unlock(&profile_list_lock);
|
|
+
|
|
+ /* FIXME: cleanup profiles references on files */
|
|
+
|
|
+ free_null_complain_profile();
|
|
+ /*
|
|
+ * 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");
|