aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2013-07-23 17:38:38 -0400
committerEric Paris <eparis@redhat.com>2013-07-25 13:01:25 -0400
commit2e5aa86609ec1cf37bcc204fd7ba6c24c2f49fec (patch)
treedfe240f974ba5437143fa8869813ac634731d860 /security/selinux
parent8bb495e3f02401ee6f76d1b1d77f3ac9f079e376 (diff)
lsm: split the xfrm_state_alloc_security() hook implementation
The xfrm_state_alloc_security() LSM hook implementation is really a multiplexed hook with two different behaviors depending on the arguments passed to it by the caller. This patch splits the LSM hook implementation into two new hook implementations, which match the LSM hooks in the rest of the kernel: * xfrm_state_alloc * xfrm_state_alloc_acquire Also included in this patch are the necessary changes to the SELinux code; no other LSMs are affected. Signed-off-by: Paul Moore <pmoore@redhat.com> Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/hooks.c3
-rw-r--r--security/selinux/include/xfrm.h4
-rw-r--r--security/selinux/xfrm.c199
3 files changed, 95 insertions, 111 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5c6f2cd2d095..d3555bdf66af 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5708,7 +5708,8 @@ static struct security_operations selinux_ops = {
5708 .xfrm_policy_clone_security = selinux_xfrm_policy_clone, 5708 .xfrm_policy_clone_security = selinux_xfrm_policy_clone,
5709 .xfrm_policy_free_security = selinux_xfrm_policy_free, 5709 .xfrm_policy_free_security = selinux_xfrm_policy_free,
5710 .xfrm_policy_delete_security = selinux_xfrm_policy_delete, 5710 .xfrm_policy_delete_security = selinux_xfrm_policy_delete,
5711 .xfrm_state_alloc_security = selinux_xfrm_state_alloc, 5711 .xfrm_state_alloc = selinux_xfrm_state_alloc,
5712 .xfrm_state_alloc_acquire = selinux_xfrm_state_alloc_acquire,
5712 .xfrm_state_free_security = selinux_xfrm_state_free, 5713 .xfrm_state_free_security = selinux_xfrm_state_free,
5713 .xfrm_state_delete_security = selinux_xfrm_state_delete, 5714 .xfrm_state_delete_security = selinux_xfrm_state_delete,
5714 .xfrm_policy_lookup = selinux_xfrm_policy_lookup, 5715 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 65f67cb0aefb..f2a2314aac1a 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -16,7 +16,9 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
16void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx); 16void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
17int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx); 17int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
18int selinux_xfrm_state_alloc(struct xfrm_state *x, 18int selinux_xfrm_state_alloc(struct xfrm_state *x,
19 struct xfrm_user_sec_ctx *sec_ctx, u32 secid); 19 struct xfrm_user_sec_ctx *uctx);
20int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
21 struct xfrm_sec_ctx *polsec, u32 secid);
20void selinux_xfrm_state_free(struct xfrm_state *x); 22void selinux_xfrm_state_free(struct xfrm_state *x);
21int selinux_xfrm_state_delete(struct xfrm_state *x); 23int selinux_xfrm_state_delete(struct xfrm_state *x);
22int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); 24int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index d03081886214..07ae0c06dfc3 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -74,6 +74,54 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
74} 74}
75 75
76/* 76/*
77 * Allocates a xfrm_sec_state and populates it using the supplied security
78 * xfrm_user_sec_ctx context.
79 */
80static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
81 struct xfrm_user_sec_ctx *uctx)
82{
83 int rc;
84 const struct task_security_struct *tsec = current_security();
85 struct xfrm_sec_ctx *ctx = NULL;
86 u32 str_len;
87
88 if (ctxp == NULL || uctx == NULL ||
89 uctx->ctx_doi != XFRM_SC_DOI_LSM ||
90 uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
91 return -EINVAL;
92
93 str_len = uctx->ctx_len;
94 if (str_len >= PAGE_SIZE)
95 return -ENOMEM;
96
97 ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL);
98 if (!ctx)
99 return -ENOMEM;
100
101 ctx->ctx_doi = XFRM_SC_DOI_LSM;
102 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
103 ctx->ctx_len = str_len;
104 memcpy(ctx->ctx_str, &uctx[1], str_len);
105 ctx->ctx_str[str_len] = '\0';
106 rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid);
107 if (rc)
108 goto err;
109
110 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
111 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
112 if (rc)
113 goto err;
114
115 *ctxp = ctx;
116 atomic_inc(&selinux_xfrm_refcount);
117 return 0;
118
119err:
120 kfree(ctx);
121 return rc;
122}
123
124/*
77 * LSM hook implementation that authorizes that a flow can use 125 * LSM hook implementation that authorizes that a flow can use
78 * a xfrm policy rule. 126 * a xfrm policy rule.
79 */ 127 */
@@ -191,111 +239,13 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
191} 239}
192 240
193/* 241/*
194 * Security blob allocation for xfrm_policy and xfrm_state
195 * CTX does not have a meaningful value on input
196 */
197static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
198 struct xfrm_user_sec_ctx *uctx, u32 sid)
199{
200 int rc = 0;
201 const struct task_security_struct *tsec = current_security();
202 struct xfrm_sec_ctx *ctx = NULL;
203 char *ctx_str = NULL;
204 u32 str_len;
205
206 BUG_ON(uctx && sid);
207
208 if (!uctx)
209 goto not_from_user;
210
211 if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
212 return -EINVAL;
213
214 str_len = uctx->ctx_len;
215 if (str_len >= PAGE_SIZE)
216 return -ENOMEM;
217
218 *ctxp = ctx = kmalloc(sizeof(*ctx) +
219 str_len + 1,
220 GFP_KERNEL);
221
222 if (!ctx)
223 return -ENOMEM;
224
225 ctx->ctx_doi = uctx->ctx_doi;
226 ctx->ctx_len = str_len;
227 ctx->ctx_alg = uctx->ctx_alg;
228
229 memcpy(ctx->ctx_str,
230 uctx+1,
231 str_len);
232 ctx->ctx_str[str_len] = 0;
233 rc = security_context_to_sid(ctx->ctx_str,
234 str_len,
235 &ctx->ctx_sid);
236
237 if (rc)
238 goto out;
239
240 /*
241 * Does the subject have permission to set security context?
242 */
243 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
244 SECCLASS_ASSOCIATION,
245 ASSOCIATION__SETCONTEXT, NULL);
246 if (rc)
247 goto out;
248
249 return rc;
250
251not_from_user:
252 rc = security_sid_to_context(sid, &ctx_str, &str_len);
253 if (rc)
254 goto out;
255
256 *ctxp = ctx = kmalloc(sizeof(*ctx) +
257 str_len,
258 GFP_ATOMIC);
259
260 if (!ctx) {
261 rc = -ENOMEM;
262 goto out;
263 }
264
265 ctx->ctx_doi = XFRM_SC_DOI_LSM;
266 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
267 ctx->ctx_sid = sid;
268 ctx->ctx_len = str_len;
269 memcpy(ctx->ctx_str,
270 ctx_str,
271 str_len);
272
273 goto out2;
274
275out:
276 *ctxp = NULL;
277 kfree(ctx);
278out2:
279 kfree(ctx_str);
280 return rc;
281}
282
283/*
284 * LSM hook implementation that allocs and transfers uctx spec to 242 * LSM hook implementation that allocs and transfers uctx spec to
285 * xfrm_policy. 243 * xfrm_policy.
286 */ 244 */
287int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, 245int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
288 struct xfrm_user_sec_ctx *uctx) 246 struct xfrm_user_sec_ctx *uctx)
289{ 247{
290 int err; 248 return selinux_xfrm_alloc_user(ctxp, uctx);
291
292 BUG_ON(!uctx);
293
294 err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
295 if (err == 0)
296 atomic_inc(&selinux_xfrm_refcount);
297
298 return err;
299} 249}
300 250
301 251
@@ -347,20 +297,51 @@ int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
347} 297}
348 298
349/* 299/*
350 * LSM hook implementation that allocs and transfers sec_ctx spec to 300 * LSM hook implementation that allocates a xfrm_sec_state, populates it using
351 * xfrm_state. 301 * the supplied security context, and assigns it to the xfrm_state.
302 */
303int selinux_xfrm_state_alloc(struct xfrm_state *x,
304 struct xfrm_user_sec_ctx *uctx)
305{
306 return selinux_xfrm_alloc_user(&x->security, uctx);
307}
308
309/*
310 * LSM hook implementation that allocates a xfrm_sec_state and populates based
311 * on a secid.
352 */ 312 */
353int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx, 313int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
354 u32 secid) 314 struct xfrm_sec_ctx *polsec, u32 secid)
355{ 315{
356 int err; 316 int rc;
317 struct xfrm_sec_ctx *ctx;
318 char *ctx_str = NULL;
319 int str_len;
357 320
358 BUG_ON(!x); 321 if (!polsec)
322 return 0;
359 323
360 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid); 324 if (secid == 0)
361 if (err == 0) 325 return -EINVAL;
362 atomic_inc(&selinux_xfrm_refcount); 326
363 return err; 327 rc = security_sid_to_context(secid, &ctx_str, &str_len);
328 if (rc)
329 return rc;
330
331 ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
332 if (!ctx)
333 return -ENOMEM;
334
335 ctx->ctx_doi = XFRM_SC_DOI_LSM;
336 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
337 ctx->ctx_sid = secid;
338 ctx->ctx_len = str_len;
339 memcpy(ctx->ctx_str, ctx_str, str_len);
340 kfree(ctx_str);
341
342 x->security = ctx;
343 atomic_inc(&selinux_xfrm_refcount);
344 return 0;
364} 345}
365 346
366/* 347/*