summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2018-09-21 20:19:37 -0400
committerKees Cook <keescook@chromium.org>2019-01-08 16:18:45 -0500
commitf4ad8f2c40769b3cc9497ba0883bbaf823f7752f (patch)
treeae8e8bfc5a3abfaa5ea3c90908efd941a230bbdf
parentafb1cbe37440c7f38b9cf46fc331cc9dfd5cce21 (diff)
LSM: Infrastructure management of the task security
Move management of the task_struct->security blob out of the individual security modules and into the security infrastructure. Instead of allocating the blobs from within the modules the modules tell the infrastructure how much space is required, and the space is allocated there. The only user of this blob is AppArmor. The AppArmor use is abstracted to avoid future conflict. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Reviewed-by: Kees Cook <keescook@chromium.org> [kees: adjusted for ordered init series] Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r--include/linux/lsm_hooks.h2
-rw-r--r--security/apparmor/include/task.h18
-rw-r--r--security/apparmor/lsm.c15
-rw-r--r--security/security.c54
4 files changed, 62 insertions, 27 deletions
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 1c798e842de2..9b39fefa88c4 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -2034,6 +2034,7 @@ struct lsm_blob_sizes {
2034 int lbs_cred; 2034 int lbs_cred;
2035 int lbs_file; 2035 int lbs_file;
2036 int lbs_inode; 2036 int lbs_inode;
2037 int lbs_task;
2037}; 2038};
2038 2039
2039/* 2040/*
@@ -2109,6 +2110,7 @@ extern int lsm_inode_alloc(struct inode *inode);
2109 2110
2110#ifdef CONFIG_SECURITY 2111#ifdef CONFIG_SECURITY
2111void __init lsm_early_cred(struct cred *cred); 2112void __init lsm_early_cred(struct cred *cred);
2113void __init lsm_early_task(struct task_struct *task);
2112#endif 2114#endif
2113 2115
2114#endif /* ! __LINUX_LSM_HOOKS_H */ 2116#endif /* ! __LINUX_LSM_HOOKS_H */
diff --git a/security/apparmor/include/task.h b/security/apparmor/include/task.h
index 55edaa1d83f8..039c1e60887a 100644
--- a/security/apparmor/include/task.h
+++ b/security/apparmor/include/task.h
@@ -14,7 +14,10 @@
14#ifndef __AA_TASK_H 14#ifndef __AA_TASK_H
15#define __AA_TASK_H 15#define __AA_TASK_H
16 16
17#define task_ctx(X) ((X)->security) 17static inline struct aa_task_ctx *task_ctx(struct task_struct *task)
18{
19 return task->security;
20}
18 21
19/* 22/*
20 * struct aa_task_ctx - information for current task label change 23 * struct aa_task_ctx - information for current task label change
@@ -37,17 +40,6 @@ int aa_restore_previous_label(u64 cookie);
37struct aa_label *aa_get_task_label(struct task_struct *task); 40struct aa_label *aa_get_task_label(struct task_struct *task);
38 41
39/** 42/**
40 * aa_alloc_task_ctx - allocate a new task_ctx
41 * @flags: gfp flags for allocation
42 *
43 * Returns: allocated buffer or NULL on failure
44 */
45static inline struct aa_task_ctx *aa_alloc_task_ctx(gfp_t flags)
46{
47 return kzalloc(sizeof(struct aa_task_ctx), flags);
48}
49
50/**
51 * aa_free_task_ctx - free a task_ctx 43 * aa_free_task_ctx - free a task_ctx
52 * @ctx: task_ctx to free (MAYBE NULL) 44 * @ctx: task_ctx to free (MAYBE NULL)
53 */ 45 */
@@ -57,8 +49,6 @@ static inline void aa_free_task_ctx(struct aa_task_ctx *ctx)
57 aa_put_label(ctx->nnp); 49 aa_put_label(ctx->nnp);
58 aa_put_label(ctx->previous); 50 aa_put_label(ctx->previous);
59 aa_put_label(ctx->onexec); 51 aa_put_label(ctx->onexec);
60
61 kzfree(ctx);
62 } 52 }
63} 53}
64 54
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 6821187b06ad..60ef71268ccf 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -94,19 +94,14 @@ static void apparmor_task_free(struct task_struct *task)
94{ 94{
95 95
96 aa_free_task_ctx(task_ctx(task)); 96 aa_free_task_ctx(task_ctx(task));
97 task_ctx(task) = NULL;
98} 97}
99 98
100static int apparmor_task_alloc(struct task_struct *task, 99static int apparmor_task_alloc(struct task_struct *task,
101 unsigned long clone_flags) 100 unsigned long clone_flags)
102{ 101{
103 struct aa_task_ctx *new = aa_alloc_task_ctx(GFP_KERNEL); 102 struct aa_task_ctx *new = task_ctx(task);
104
105 if (!new)
106 return -ENOMEM;
107 103
108 aa_dup_task_ctx(new, task_ctx(current)); 104 aa_dup_task_ctx(new, task_ctx(current));
109 task_ctx(task) = new;
110 105
111 return 0; 106 return 0;
112} 107}
@@ -1157,6 +1152,7 @@ static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
1157struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { 1152struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = {
1158 .lbs_cred = sizeof(struct aa_task_ctx *), 1153 .lbs_cred = sizeof(struct aa_task_ctx *),
1159 .lbs_file = sizeof(struct aa_file_ctx), 1154 .lbs_file = sizeof(struct aa_file_ctx),
1155 .lbs_task = sizeof(struct aa_task_ctx),
1160}; 1156};
1161 1157
1162static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 1158static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
@@ -1487,15 +1483,10 @@ static int param_set_mode(const char *val, const struct kernel_param *kp)
1487static int __init set_init_ctx(void) 1483static int __init set_init_ctx(void)
1488{ 1484{
1489 struct cred *cred = (struct cred *)current->real_cred; 1485 struct cred *cred = (struct cred *)current->real_cred;
1490 struct aa_task_ctx *ctx;
1491
1492 ctx = aa_alloc_task_ctx(GFP_KERNEL);
1493 if (!ctx)
1494 return -ENOMEM;
1495 1486
1496 lsm_early_cred(cred); 1487 lsm_early_cred(cred);
1488 lsm_early_task(current);
1497 set_cred_label(cred, aa_get_label(ns_unconfined(root_ns))); 1489 set_cred_label(cred, aa_get_label(ns_unconfined(root_ns)));
1498 task_ctx(current) = ctx;
1499 1490
1500 return 0; 1491 return 0;
1501} 1492}
diff --git a/security/security.c b/security/security.c
index 4989fb65e662..e59a1e1514ee 100644
--- a/security/security.c
+++ b/security/security.c
@@ -169,6 +169,7 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
169 if (needed->lbs_inode && blob_sizes.lbs_inode == 0) 169 if (needed->lbs_inode && blob_sizes.lbs_inode == 0)
170 blob_sizes.lbs_inode = sizeof(struct rcu_head); 170 blob_sizes.lbs_inode = sizeof(struct rcu_head);
171 lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode); 171 lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
172 lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
172} 173}
173 174
174/* Prepare LSM for initialization. */ 175/* Prepare LSM for initialization. */
@@ -292,6 +293,7 @@ static void __init ordered_lsm_init(void)
292 init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); 293 init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
293 init_debug("file blob size = %d\n", blob_sizes.lbs_file); 294 init_debug("file blob size = %d\n", blob_sizes.lbs_file);
294 init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); 295 init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
296 init_debug("task blob size = %d\n", blob_sizes.lbs_task);
295 297
296 /* 298 /*
297 * Create any kmem_caches needed for blobs 299 * Create any kmem_caches needed for blobs
@@ -515,6 +517,46 @@ int lsm_inode_alloc(struct inode *inode)
515 return 0; 517 return 0;
516} 518}
517 519
520/**
521 * lsm_task_alloc - allocate a composite task blob
522 * @task: the task that needs a blob
523 *
524 * Allocate the task blob for all the modules
525 *
526 * Returns 0, or -ENOMEM if memory can't be allocated.
527 */
528int lsm_task_alloc(struct task_struct *task)
529{
530 if (blob_sizes.lbs_task == 0) {
531 task->security = NULL;
532 return 0;
533 }
534
535 task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL);
536 if (task->security == NULL)
537 return -ENOMEM;
538 return 0;
539}
540
541/**
542 * lsm_early_task - during initialization allocate a composite task blob
543 * @task: the task that needs a blob
544 *
545 * Allocate the task blob for all the modules if it's not already there
546 */
547void __init lsm_early_task(struct task_struct *task)
548{
549 int rc;
550
551 if (task == NULL)
552 panic("%s: task cred.\n", __func__);
553 if (task->security != NULL)
554 return;
555 rc = lsm_task_alloc(task);
556 if (rc)
557 panic("%s: Early task alloc failed.\n", __func__);
558}
559
518/* 560/*
519 * Hook list operation macros. 561 * Hook list operation macros.
520 * 562 *
@@ -1359,12 +1401,22 @@ int security_file_open(struct file *file)
1359 1401
1360int security_task_alloc(struct task_struct *task, unsigned long clone_flags) 1402int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
1361{ 1403{
1362 return call_int_hook(task_alloc, 0, task, clone_flags); 1404 int rc = lsm_task_alloc(task);
1405
1406 if (rc)
1407 return rc;
1408 rc = call_int_hook(task_alloc, 0, task, clone_flags);
1409 if (unlikely(rc))
1410 security_task_free(task);
1411 return rc;
1363} 1412}
1364 1413
1365void security_task_free(struct task_struct *task) 1414void security_task_free(struct task_struct *task)
1366{ 1415{
1367 call_void_hook(task_free, task); 1416 call_void_hook(task_free, task);
1417
1418 kfree(task->security);
1419 task->security = NULL;
1368} 1420}
1369 1421
1370int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) 1422int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)