aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-01-27 06:53:53 -0500
committerJohn Johansen <john.johansen@canonical.com>2018-02-09 14:30:01 -0500
commitd9087c49d4388e3f35f09a5cf7ed6e09c9106604 (patch)
treecdc1032157a2cb4ceb8c8f5278f7a280acf9d463 /security
parent3b529a7600d834f450ac244f43a7c082687284b4 (diff)
apparmor: drop cred_ctx and reference the label directly
With the task domain change information now stored in the task->security context, the cred->security context only stores the label. We can get rid of the cred_ctx and directly reference the label, removing a layer of indirection, and unneeded extra allocations. Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/context.c83
-rw-r--r--security/apparmor/domain.c14
-rw-r--r--security/apparmor/include/context.h24
-rw-r--r--security/apparmor/lsm.c55
4 files changed, 47 insertions, 129 deletions
diff --git a/security/apparmor/context.c b/security/apparmor/context.c
index 432672b18945..70e4a094add8 100644
--- a/security/apparmor/context.c
+++ b/security/apparmor/context.c
@@ -13,11 +13,9 @@
13 * License. 13 * License.
14 * 14 *
15 * 15 *
16 * AppArmor sets confinement on every task, via the the aa_cred_ctx and 16 * AppArmor sets confinement on every task, via the cred_label() which
17 * the aa_cred_ctx.label, both of which are required and are not allowed 17 * is required and are not allowed to be NULL. The cred_label is
18 * to be NULL. The aa_cred_ctx is not reference counted and is unique 18 * reference counted.
19 * to each cred (which is reference count). The label pointed to by
20 * the cred_ctx is reference counted.
21 * 19 *
22 * TODO 20 * TODO
23 * If a task uses change_hat it currently does not return to the old 21 * If a task uses change_hat it currently does not return to the old
@@ -29,40 +27,6 @@
29#include "include/context.h" 27#include "include/context.h"
30#include "include/policy.h" 28#include "include/policy.h"
31 29
32/**
33 * aa_alloc_cred_ctx - allocate a new cred_ctx
34 * @flags: gfp flags for allocation
35 *
36 * Returns: allocated buffer or NULL on failure
37 */
38struct aa_cred_ctx *aa_alloc_cred_ctx(gfp_t flags)
39{
40 return kzalloc(sizeof(struct aa_cred_ctx), flags);
41}
42
43/**
44 * aa_free_cred_ctx - free a cred_ctx
45 * @ctx: cred_ctx to free (MAYBE NULL)
46 */
47void aa_free_cred_ctx(struct aa_cred_ctx *ctx)
48{
49 if (ctx) {
50 aa_put_label(ctx->label);
51
52 kzfree(ctx);
53 }
54}
55
56/**
57 * aa_dup_cred_ctx - duplicate a task context, incrementing reference counts
58 * @new: a blank task context (NOT NULL)
59 * @old: the task context to copy (NOT NULL)
60 */
61void aa_dup_cred_ctx(struct aa_cred_ctx *new, const struct aa_cred_ctx *old)
62{
63 *new = *old;
64 aa_get_label(new->label);
65}
66 30
67/** 31/**
68 * aa_get_task_label - Get another task's label 32 * aa_get_task_label - Get another task's label
@@ -126,11 +90,12 @@ void aa_dup_task_ctx(struct aa_task_ctx *new, const struct aa_task_ctx *old)
126 */ 90 */
127int aa_replace_current_label(struct aa_label *label) 91int aa_replace_current_label(struct aa_label *label)
128{ 92{
129 struct aa_cred_ctx *ctx = current_cred_ctx(); 93 struct aa_label *old = aa_current_raw_label();
130 struct cred *new; 94 struct cred *new;
95
131 AA_BUG(!label); 96 AA_BUG(!label);
132 97
133 if (ctx->label == label) 98 if (old == label)
134 return 0; 99 return 0;
135 100
136 if (current_cred() != current_real_cred()) 101 if (current_cred() != current_real_cred())
@@ -140,22 +105,22 @@ int aa_replace_current_label(struct aa_label *label)
140 if (!new) 105 if (!new)
141 return -ENOMEM; 106 return -ENOMEM;
142 107
143 ctx = cred_ctx(new); 108 if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
144 if (unconfined(label) || (labels_ns(ctx->label) != labels_ns(label))) 109 /*
145 /* if switching to unconfined or a different label namespace 110 * if switching to unconfined or a different label namespace
146 * clear out context state 111 * clear out context state
147 */ 112 */
148 aa_clear_task_ctx_trans(current_task_ctx()); 113 aa_clear_task_ctx_trans(current_task_ctx());
149 114
150 /* 115 /*
151 * be careful switching ctx->profile, when racing replacement it 116 * be careful switching cred label, when racing replacement it
152 * is possible that ctx->profile->proxy->profile is the reference 117 * is possible that the cred labels's->proxy->label is the reference
153 * keeping @profile valid, so make sure to get its reference before 118 * keeping @label valid, so make sure to get its reference before
154 * dropping the reference on ctx->profile 119 * dropping the reference on the cred's label
155 */ 120 */
156 aa_get_label(label); 121 aa_get_label(label);
157 aa_put_label(ctx->label); 122 aa_put_label(cred_label(new));
158 ctx->label = label; 123 cred_label(new) = label;
159 124
160 commit_creds(new); 125 commit_creds(new);
161 return 0; 126 return 0;
@@ -193,26 +158,26 @@ int aa_set_current_hat(struct aa_label *label, u64 token)
193{ 158{
194 struct aa_task_ctx *tctx = current_task_ctx(); 159 struct aa_task_ctx *tctx = current_task_ctx();
195 struct aa_cred_ctx *ctx; 160 struct aa_cred_ctx *ctx;
196 struct cred *new = prepare_creds(); 161 struct cred *new;
197 162
163 new = prepare_creds();
198 if (!new) 164 if (!new)
199 return -ENOMEM; 165 return -ENOMEM;
200 AA_BUG(!label); 166 AA_BUG(!label);
201 167
202 ctx = cred_ctx(new);
203 if (!tctx->previous) { 168 if (!tctx->previous) {
204 /* transfer refcount */ 169 /* transfer refcount */
205 tctx->previous = ctx->label; 170 tctx->previous = cred_label(new);
206 tctx->token = token; 171 tctx->token = token;
207 } else if (tctx->token == token) { 172 } else if (tctx->token == token) {
208 aa_put_label(ctx->label); 173 aa_put_label(cred_label(new));
209 } else { 174 } else {
210 /* previous_profile && ctx->token != token */ 175 /* previous_profile && ctx->token != token */
211 abort_creds(new); 176 abort_creds(new);
212 return -EACCES; 177 return -EACCES;
213 } 178 }
214 179
215 ctx->label = aa_get_newest_label(label); 180 cred_label(new) = aa_get_newest_label(label);
216 /* clear exec on switching context */ 181 /* clear exec on switching context */
217 aa_put_label(tctx->onexec); 182 aa_put_label(tctx->onexec);
218 tctx->onexec = NULL; 183 tctx->onexec = NULL;
@@ -233,7 +198,6 @@ int aa_set_current_hat(struct aa_label *label, u64 token)
233int aa_restore_previous_label(u64 token) 198int aa_restore_previous_label(u64 token)
234{ 199{
235 struct aa_task_ctx *tctx = current_task_ctx(); 200 struct aa_task_ctx *tctx = current_task_ctx();
236 struct aa_cred_ctx *ctx;
237 struct cred *new; 201 struct cred *new;
238 202
239 if (tctx->token != token) 203 if (tctx->token != token)
@@ -245,11 +209,10 @@ int aa_restore_previous_label(u64 token)
245 new = prepare_creds(); 209 new = prepare_creds();
246 if (!new) 210 if (!new)
247 return -ENOMEM; 211 return -ENOMEM;
248 ctx = cred_ctx(new);
249 212
250 aa_put_label(ctx->label); 213 aa_put_label(cred_label(new));
251 ctx->label = aa_get_newest_label(tctx->previous); 214 cred_label(new) = aa_get_newest_label(tctx->previous);
252 AA_BUG(!ctx->label); 215 AA_BUG(!cred_label(new));
253 /* clear exec && prev information when restoring to previous context */ 216 /* clear exec && prev information when restoring to previous context */
254 aa_clear_task_ctx_trans(tctx); 217 aa_clear_task_ctx_trans(tctx);
255 218
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index b90759a765b5..5285938680e0 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -779,7 +779,6 @@ static struct aa_label *handle_onexec(struct aa_label *label,
779 */ 779 */
780int apparmor_bprm_set_creds(struct linux_binprm *bprm) 780int apparmor_bprm_set_creds(struct linux_binprm *bprm)
781{ 781{
782 struct aa_cred_ctx *ctx;
783 struct aa_task_ctx *tctx; 782 struct aa_task_ctx *tctx;
784 struct aa_label *label, *new = NULL; 783 struct aa_label *label, *new = NULL;
785 struct aa_profile *profile; 784 struct aa_profile *profile;
@@ -795,12 +794,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
795 if (bprm->called_set_creds) 794 if (bprm->called_set_creds)
796 return 0; 795 return 0;
797 796
798 ctx = cred_ctx(bprm->cred);
799 tctx = current_task_ctx(); 797 tctx = current_task_ctx();
800 AA_BUG(!ctx); 798 AA_BUG(!cred_label(bprm->cred));
801 AA_BUG(!tctx); 799 AA_BUG(!tctx);
802 800
803 label = aa_get_newest_label(ctx->label); 801 label = aa_get_newest_label(cred_label(bprm->cred));
804 802
805 /* buffer freed below, name is pointer into buffer */ 803 /* buffer freed below, name is pointer into buffer */
806 get_buffers(buffer); 804 get_buffers(buffer);
@@ -856,9 +854,9 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
856 } 854 }
857 bprm->per_clear |= PER_CLEAR_ON_SETID; 855 bprm->per_clear |= PER_CLEAR_ON_SETID;
858 } 856 }
859 aa_put_label(ctx->label); 857 aa_put_label(cred_label(bprm->cred));
860 /* transfer reference, released when ctx is freed */ 858 /* transfer reference, released when cred is freed */
861 ctx->label = new; 859 cred_label(bprm->cred) = new;
862 860
863done: 861done:
864 aa_put_label(label); 862 aa_put_label(label);
@@ -1049,7 +1047,6 @@ build:
1049int aa_change_hat(const char *hats[], int count, u64 token, int flags) 1047int aa_change_hat(const char *hats[], int count, u64 token, int flags)
1050{ 1048{
1051 const struct cred *cred; 1049 const struct cred *cred;
1052 struct aa_cred_ctx *ctx;
1053 struct aa_task_ctx *tctx; 1050 struct aa_task_ctx *tctx;
1054 struct aa_label *label, *previous, *new = NULL, *target = NULL; 1051 struct aa_label *label, *previous, *new = NULL, *target = NULL;
1055 struct aa_profile *profile; 1052 struct aa_profile *profile;
@@ -1070,7 +1067,6 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
1070 1067
1071 /* released below */ 1068 /* released below */
1072 cred = get_current_cred(); 1069 cred = get_current_cred();
1073 ctx = cred_ctx(cred);
1074 tctx = current_task_ctx(); 1070 tctx = current_task_ctx();
1075 label = aa_get_newest_cred_label(cred); 1071 label = aa_get_newest_cred_label(cred);
1076 previous = aa_get_newest_label(tctx->previous); 1072 previous = aa_get_newest_label(tctx->previous);
diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
index c3b51d88275b..8d36c14bc76d 100644
--- a/security/apparmor/include/context.h
+++ b/security/apparmor/include/context.h
@@ -22,21 +22,11 @@
22#include "label.h" 22#include "label.h"
23#include "policy_ns.h" 23#include "policy_ns.h"
24 24
25#define cred_ctx(X) ((X)->security)
26#define current_cred_ctx() cred_ctx(current_cred())
27
28#define task_ctx(X) ((X)->security) 25#define task_ctx(X) ((X)->security)
29#define current_task_ctx() (task_ctx(current)) 26#define current_task_ctx() (task_ctx(current))
27#define cred_label(X) ((X)->security)
30 28
31/** 29/*
32 * struct aa_cred_ctx - primary label for confined tasks
33 * @label: the current label (NOT NULL)
34 */
35struct aa_cred_ctx {
36 struct aa_label *label;
37};
38
39/**
40 * struct aa_task_ctx - information for current task label change 30 * struct aa_task_ctx - information for current task label change
41 * @onexec: profile to transition to on next exec (MAY BE NULL) 31 * @onexec: profile to transition to on next exec (MAY BE NULL)
42 * @previous: profile the task may return to (MAY BE NULL) 32 * @previous: profile the task may return to (MAY BE NULL)
@@ -48,10 +38,6 @@ struct aa_task_ctx {
48 u64 token; 38 u64 token;
49}; 39};
50 40
51struct aa_cred_ctx *aa_alloc_cred_ctx(gfp_t flags);
52void aa_free_cred_ctx(struct aa_cred_ctx *ctx);
53void aa_dup_cred_ctx(struct aa_cred_ctx *new, const struct aa_cred_ctx *old);
54
55struct aa_task_ctx *aa_alloc_task_ctx(gfp_t flags); 41struct aa_task_ctx *aa_alloc_task_ctx(gfp_t flags);
56void aa_free_task_ctx(struct aa_task_ctx *ctx); 42void aa_free_task_ctx(struct aa_task_ctx *ctx);
57void aa_dup_task_ctx(struct aa_task_ctx *new, const struct aa_task_ctx *old); 43void aa_dup_task_ctx(struct aa_task_ctx *new, const struct aa_task_ctx *old);
@@ -73,10 +59,10 @@ struct aa_label *aa_get_task_label(struct task_struct *task);
73 */ 59 */
74static inline struct aa_label *aa_cred_raw_label(const struct cred *cred) 60static inline struct aa_label *aa_cred_raw_label(const struct cred *cred)
75{ 61{
76 struct aa_cred_ctx *ctx = cred_ctx(cred); 62 struct aa_label *label = cred_label(cred);
77 63
78 AA_BUG(!ctx || !ctx->label); 64 AA_BUG(!label);
79 return ctx->label; 65 return label;
80} 66}
81 67
82/** 68/**
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index a1d63d93b862..628c6a07df64 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -51,12 +51,12 @@ DEFINE_PER_CPU(struct aa_buffers, aa_buffers);
51 */ 51 */
52 52
53/* 53/*
54 * free the associated aa_cred_ctx and put its labels 54 * put the associated labels
55 */ 55 */
56static void apparmor_cred_free(struct cred *cred) 56static void apparmor_cred_free(struct cred *cred)
57{ 57{
58 aa_free_cred_ctx(cred_ctx(cred)); 58 aa_put_label(cred_label(cred));
59 cred_ctx(cred) = NULL; 59 cred_label(cred) = NULL;
60} 60}
61 61
62/* 62/*
@@ -64,30 +64,17 @@ static void apparmor_cred_free(struct cred *cred)
64 */ 64 */
65static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) 65static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
66{ 66{
67 /* freed by apparmor_cred_free */ 67 cred_label(cred) = NULL;
68 struct aa_cred_ctx *ctx = aa_alloc_cred_ctx(gfp);
69
70 if (!ctx)
71 return -ENOMEM;
72
73 cred_ctx(cred) = ctx;
74 return 0; 68 return 0;
75} 69}
76 70
77/* 71/*
78 * prepare new aa_cred_ctx for modification by prepare_cred block 72 * prepare new cred label for modification by prepare_cred block
79 */ 73 */
80static int apparmor_cred_prepare(struct cred *new, const struct cred *old, 74static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
81 gfp_t gfp) 75 gfp_t gfp)
82{ 76{
83 /* freed by apparmor_cred_free */ 77 cred_label(new) = aa_get_newest_label(cred_label(old));
84 struct aa_cred_ctx *ctx = aa_alloc_cred_ctx(gfp);
85
86 if (!ctx)
87 return -ENOMEM;
88
89 aa_dup_cred_ctx(ctx, cred_ctx(old));
90 cred_ctx(new) = ctx;
91 return 0; 78 return 0;
92} 79}
93 80
@@ -96,10 +83,7 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
96 */ 83 */
97static void apparmor_cred_transfer(struct cred *new, const struct cred *old) 84static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
98{ 85{
99 const struct aa_cred_ctx *old_ctx = cred_ctx(old); 86 cred_label(new) = aa_get_newest_label(cred_label(old));
100 struct aa_cred_ctx *new_ctx = cred_ctx(new);
101
102 aa_dup_cred_ctx(new_ctx, old_ctx);
103} 87}
104 88
105static void apparmor_task_free(struct task_struct *task) 89static void apparmor_task_free(struct task_struct *task)
@@ -599,11 +583,10 @@ static int apparmor_getprocattr(struct task_struct *task, char *name,
599 /* released below */ 583 /* released below */
600 const struct cred *cred = get_task_cred(task); 584 const struct cred *cred = get_task_cred(task);
601 struct aa_task_ctx *tctx = current_task_ctx(); 585 struct aa_task_ctx *tctx = current_task_ctx();
602 struct aa_cred_ctx *ctx = cred_ctx(cred);
603 struct aa_label *label = NULL; 586 struct aa_label *label = NULL;
604 587
605 if (strcmp(name, "current") == 0) 588 if (strcmp(name, "current") == 0)
606 label = aa_get_newest_label(ctx->label); 589 label = aa_get_newest_label(cred_label(cred));
607 else if (strcmp(name, "prev") == 0 && tctx->previous) 590 else if (strcmp(name, "prev") == 0 && tctx->previous)
608 label = aa_get_newest_label(tctx->previous); 591 label = aa_get_newest_label(tctx->previous);
609 else if (strcmp(name, "exec") == 0 && tctx->onexec) 592 else if (strcmp(name, "exec") == 0 && tctx->onexec)
@@ -700,11 +683,11 @@ fail:
700static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) 683static void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
701{ 684{
702 struct aa_label *label = aa_current_raw_label(); 685 struct aa_label *label = aa_current_raw_label();
703 struct aa_cred_ctx *new_ctx = cred_ctx(bprm->cred); 686 struct aa_label *new_label = cred_label(bprm->cred);
704 687
705 /* bail out if unconfined or not changing profile */ 688 /* bail out if unconfined or not changing profile */
706 if ((new_ctx->label->proxy == label->proxy) || 689 if ((new_label->proxy == label->proxy) ||
707 (unconfined(new_ctx->label))) 690 (unconfined(new_label)))
708 return; 691 return;
709 692
710 aa_inherit_files(bprm->cred, current->files); 693 aa_inherit_files(bprm->cred, current->files);
@@ -712,7 +695,7 @@ static void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
712 current->pdeath_signal = 0; 695 current->pdeath_signal = 0;
713 696
714 /* reset soft limits and set hard limits for the new label */ 697 /* reset soft limits and set hard limits for the new label */
715 __aa_transition_rlimits(label, new_ctx->label); 698 __aa_transition_rlimits(label, new_label);
716} 699}
717 700
718/** 701/**
@@ -1050,26 +1033,16 @@ static int param_set_mode(const char *val, const struct kernel_param *kp)
1050static int __init set_init_ctx(void) 1033static int __init set_init_ctx(void)
1051{ 1034{
1052 struct cred *cred = (struct cred *)current->real_cred; 1035 struct cred *cred = (struct cred *)current->real_cred;
1053 struct aa_cred_ctx *ctx;
1054 struct aa_task_ctx *tctx; 1036 struct aa_task_ctx *tctx;
1055 1037
1056 ctx = aa_alloc_cred_ctx(GFP_KERNEL);
1057 if (!ctx)
1058 goto fail_cred;
1059 tctx = aa_alloc_task_ctx(GFP_KERNEL); 1038 tctx = aa_alloc_task_ctx(GFP_KERNEL);
1060 if (!tctx) 1039 if (!tctx)
1061 goto fail_task; 1040 return -ENOMEM;
1062 1041
1063 ctx->label = aa_get_label(ns_unconfined(root_ns)); 1042 cred_label(cred) = aa_get_label(ns_unconfined(root_ns));
1064 cred_ctx(cred) = ctx;
1065 task_ctx(current) = tctx; 1043 task_ctx(current) = tctx;
1066 1044
1067 return 0; 1045 return 0;
1068
1069fail_task:
1070 aa_free_cred_ctx(ctx);
1071fail_cred:
1072 return -ENOMEM;
1073} 1046}
1074 1047
1075static void destroy_buffers(void) 1048static void destroy_buffers(void)