aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/security.h26
-rw-r--r--security/capability.c15
-rw-r--r--security/security.c13
-rw-r--r--security/selinux/hooks.c3
-rw-r--r--security/selinux/include/xfrm.h4
-rw-r--r--security/selinux/xfrm.c199
6 files changed, 128 insertions, 132 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index 4686491852a7..e5a5e8a41e55 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1039,17 +1039,25 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
1039 * @xfrm_policy_delete_security: 1039 * @xfrm_policy_delete_security:
1040 * @ctx contains the xfrm_sec_ctx. 1040 * @ctx contains the xfrm_sec_ctx.
1041 * Authorize deletion of xp->security. 1041 * Authorize deletion of xp->security.
1042 * @xfrm_state_alloc_security: 1042 * @xfrm_state_alloc:
1043 * @x contains the xfrm_state being added to the Security Association 1043 * @x contains the xfrm_state being added to the Security Association
1044 * Database by the XFRM system. 1044 * Database by the XFRM system.
1045 * @sec_ctx contains the security context information being provided by 1045 * @sec_ctx contains the security context information being provided by
1046 * the user-level SA generation program (e.g., setkey or racoon). 1046 * the user-level SA generation program (e.g., setkey or racoon).
1047 * @secid contains the secid from which to take the mls portion of the context.
1048 * Allocate a security structure to the x->security field; the security 1047 * Allocate a security structure to the x->security field; the security
1049 * field is initialized to NULL when the xfrm_state is allocated. Set the 1048 * field is initialized to NULL when the xfrm_state is allocated. Set the
1050 * context to correspond to either sec_ctx or polsec, with the mls portion 1049 * context to correspond to sec_ctx. Return 0 if operation was successful
1051 * taken from secid in the latter case. 1050 * (memory to allocate, legal context).
1052 * Return 0 if operation was successful (memory to allocate, legal context). 1051 * @xfrm_state_alloc_acquire:
1052 * @x contains the xfrm_state being added to the Security Association
1053 * Database by the XFRM system.
1054 * @polsec contains the policy's security context.
1055 * @secid contains the secid from which to take the mls portion of the
1056 * context.
1057 * Allocate a security structure to the x->security field; the security
1058 * field is initialized to NULL when the xfrm_state is allocated. Set the
1059 * context to correspond to secid. Return 0 if operation was successful
1060 * (memory to allocate, legal context).
1053 * @xfrm_state_free_security: 1061 * @xfrm_state_free_security:
1054 * @x contains the xfrm_state. 1062 * @x contains the xfrm_state.
1055 * Deallocate x->security. 1063 * Deallocate x->security.
@@ -1651,9 +1659,11 @@ struct security_operations {
1651 int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx); 1659 int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
1652 void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx); 1660 void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
1653 int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx); 1661 int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
1654 int (*xfrm_state_alloc_security) (struct xfrm_state *x, 1662 int (*xfrm_state_alloc) (struct xfrm_state *x,
1655 struct xfrm_user_sec_ctx *sec_ctx, 1663 struct xfrm_user_sec_ctx *sec_ctx);
1656 u32 secid); 1664 int (*xfrm_state_alloc_acquire) (struct xfrm_state *x,
1665 struct xfrm_sec_ctx *polsec,
1666 u32 secid);
1657 void (*xfrm_state_free_security) (struct xfrm_state *x); 1667 void (*xfrm_state_free_security) (struct xfrm_state *x);
1658 int (*xfrm_state_delete_security) (struct xfrm_state *x); 1668 int (*xfrm_state_delete_security) (struct xfrm_state *x);
1659 int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); 1669 int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
diff --git a/security/capability.c b/security/capability.c
index 1728d4e375db..67afc679719a 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -767,9 +767,15 @@ static int cap_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
767 return 0; 767 return 0;
768} 768}
769 769
770static int cap_xfrm_state_alloc_security(struct xfrm_state *x, 770static int cap_xfrm_state_alloc(struct xfrm_state *x,
771 struct xfrm_user_sec_ctx *sec_ctx, 771 struct xfrm_user_sec_ctx *sec_ctx)
772 u32 secid) 772{
773 return 0;
774}
775
776static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x,
777 struct xfrm_sec_ctx *polsec,
778 u32 secid)
773{ 779{
774 return 0; 780 return 0;
775} 781}
@@ -1084,7 +1090,8 @@ void __init security_fixup_ops(struct security_operations *ops)
1084 set_to_cap_if_null(ops, xfrm_policy_clone_security); 1090 set_to_cap_if_null(ops, xfrm_policy_clone_security);
1085 set_to_cap_if_null(ops, xfrm_policy_free_security); 1091 set_to_cap_if_null(ops, xfrm_policy_free_security);
1086 set_to_cap_if_null(ops, xfrm_policy_delete_security); 1092 set_to_cap_if_null(ops, xfrm_policy_delete_security);
1087 set_to_cap_if_null(ops, xfrm_state_alloc_security); 1093 set_to_cap_if_null(ops, xfrm_state_alloc);
1094 set_to_cap_if_null(ops, xfrm_state_alloc_acquire);
1088 set_to_cap_if_null(ops, xfrm_state_free_security); 1095 set_to_cap_if_null(ops, xfrm_state_free_security);
1089 set_to_cap_if_null(ops, xfrm_state_delete_security); 1096 set_to_cap_if_null(ops, xfrm_state_delete_security);
1090 set_to_cap_if_null(ops, xfrm_policy_lookup); 1097 set_to_cap_if_null(ops, xfrm_policy_lookup);
diff --git a/security/security.c b/security/security.c
index a3dce87d1aef..57e25c962968 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1322,22 +1322,17 @@ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
1322 return security_ops->xfrm_policy_delete_security(ctx); 1322 return security_ops->xfrm_policy_delete_security(ctx);
1323} 1323}
1324 1324
1325int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) 1325int security_xfrm_state_alloc(struct xfrm_state *x,
1326 struct xfrm_user_sec_ctx *sec_ctx)
1326{ 1327{
1327 return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0); 1328 return security_ops->xfrm_state_alloc(x, sec_ctx);
1328} 1329}
1329EXPORT_SYMBOL(security_xfrm_state_alloc); 1330EXPORT_SYMBOL(security_xfrm_state_alloc);
1330 1331
1331int security_xfrm_state_alloc_acquire(struct xfrm_state *x, 1332int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
1332 struct xfrm_sec_ctx *polsec, u32 secid) 1333 struct xfrm_sec_ctx *polsec, u32 secid)
1333{ 1334{
1334 if (!polsec) 1335 return security_ops->xfrm_state_alloc_acquire(x, polsec, secid);
1335 return 0;
1336 /*
1337 * We want the context to be taken from secid which is usually
1338 * from the sock.
1339 */
1340 return security_ops->xfrm_state_alloc_security(x, NULL, secid);
1341} 1336}
1342 1337
1343int security_xfrm_state_delete(struct xfrm_state *x) 1338int security_xfrm_state_delete(struct xfrm_state *x)
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/*