diff options
Diffstat (limited to 'security/apparmor/lsm.c')
-rw-r--r-- | security/apparmor/lsm.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8a887c392fdb..c249ea0e6328 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -41,6 +41,9 @@ /* Flag indicating whether initialization completed */ int apparmor_initialized __initdata; +DEFINE_PER_CPU(struct aa_buffers, aa_buffers); + + /* * LSM hook functions */ @@ -868,6 +871,43 @@ static int __init set_init_ctx(void) return 0; } +static void destroy_buffers(void) +{ + u32 i, j; + + for_each_possible_cpu(i) { + for_each_cpu_buffer(j) { + kfree(per_cpu(aa_buffers, i).buf[j]); + per_cpu(aa_buffers, i).buf[j] = NULL; + } + } +} + +static int __init alloc_buffers(void) +{ + u32 i, j; + + for_each_possible_cpu(i) { + for_each_cpu_buffer(j) { + char *buffer; + + if (cpu_to_node(i) > num_online_nodes()) + /* fallback to kmalloc for offline nodes */ + buffer = kmalloc(aa_g_path_max, GFP_KERNEL); + else + buffer = kmalloc_node(aa_g_path_max, GFP_KERNEL, + cpu_to_node(i)); + if (!buffer) { + destroy_buffers(); + return -ENOMEM; + } + per_cpu(aa_buffers, i).buf[j] = buffer; + } + } + + return 0; +} + #ifdef CONFIG_SYSCTL static int apparmor_dointvec(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) @@ -937,11 +977,17 @@ static int __init apparmor_init(void) } + error = alloc_buffers(); + if (error) { + AA_ERROR("Unable to allocate work buffers\n"); + goto buffers_out; + } + error = set_init_ctx(); if (error) { AA_ERROR("Failed to set context on init task\n"); aa_free_root_ns(); - goto alloc_out; + goto buffers_out; } security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks)); @@ -956,6 +1002,9 @@ static int __init apparmor_init(void) return error; +buffers_out: + destroy_buffers(); + alloc_out: aa_destroy_aafs(); aa_teardown_dfa_engine(); |