0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <linux/kernel.h>
0032 #include <linux/init.h>
0033 #include <linux/security.h>
0034 #include <linux/types.h>
0035 #include <linux/slab.h>
0036 #include <linux/ip.h>
0037 #include <linux/tcp.h>
0038 #include <linux/skbuff.h>
0039 #include <linux/xfrm.h>
0040 #include <net/xfrm.h>
0041 #include <net/checksum.h>
0042 #include <net/udp.h>
0043 #include <linux/atomic.h>
0044
0045 #include "avc.h"
0046 #include "objsec.h"
0047 #include "xfrm.h"
0048
0049
0050 atomic_t selinux_xfrm_refcount __read_mostly = ATOMIC_INIT(0);
0051
0052
0053
0054
0055 static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
0056 {
0057 return (ctx &&
0058 (ctx->ctx_doi == XFRM_SC_DOI_LSM) &&
0059 (ctx->ctx_alg == XFRM_SC_ALG_SELINUX));
0060 }
0061
0062
0063
0064
0065 static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
0066 {
0067 return selinux_authorizable_ctx(x->security);
0068 }
0069
0070
0071
0072
0073
0074 static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
0075 struct xfrm_user_sec_ctx *uctx,
0076 gfp_t gfp)
0077 {
0078 int rc;
0079 const struct task_security_struct *tsec = selinux_cred(current_cred());
0080 struct xfrm_sec_ctx *ctx = NULL;
0081 u32 str_len;
0082
0083 if (ctxp == NULL || uctx == NULL ||
0084 uctx->ctx_doi != XFRM_SC_DOI_LSM ||
0085 uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
0086 return -EINVAL;
0087
0088 str_len = uctx->ctx_len;
0089 if (str_len >= PAGE_SIZE)
0090 return -ENOMEM;
0091
0092 ctx = kmalloc(struct_size(ctx, ctx_str, str_len + 1), gfp);
0093 if (!ctx)
0094 return -ENOMEM;
0095
0096 ctx->ctx_doi = XFRM_SC_DOI_LSM;
0097 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
0098 ctx->ctx_len = str_len;
0099 memcpy(ctx->ctx_str, &uctx[1], str_len);
0100 ctx->ctx_str[str_len] = '\0';
0101 rc = security_context_to_sid(&selinux_state, ctx->ctx_str, str_len,
0102 &ctx->ctx_sid, gfp);
0103 if (rc)
0104 goto err;
0105
0106 rc = avc_has_perm(&selinux_state,
0107 tsec->sid, ctx->ctx_sid,
0108 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
0109 if (rc)
0110 goto err;
0111
0112 *ctxp = ctx;
0113 atomic_inc(&selinux_xfrm_refcount);
0114 return 0;
0115
0116 err:
0117 kfree(ctx);
0118 return rc;
0119 }
0120
0121
0122
0123
0124 static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
0125 {
0126 if (!ctx)
0127 return;
0128
0129 atomic_dec(&selinux_xfrm_refcount);
0130 kfree(ctx);
0131 }
0132
0133
0134
0135
0136 static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
0137 {
0138 const struct task_security_struct *tsec = selinux_cred(current_cred());
0139
0140 if (!ctx)
0141 return 0;
0142
0143 return avc_has_perm(&selinux_state,
0144 tsec->sid, ctx->ctx_sid,
0145 SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
0146 NULL);
0147 }
0148
0149
0150
0151
0152
0153 int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid)
0154 {
0155 int rc;
0156
0157
0158
0159 if (!ctx)
0160 return 0;
0161
0162
0163 if (!selinux_authorizable_ctx(ctx))
0164 return -EINVAL;
0165
0166 rc = avc_has_perm(&selinux_state,
0167 fl_secid, ctx->ctx_sid,
0168 SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
0169 return (rc == -EACCES ? -ESRCH : rc);
0170 }
0171
0172
0173
0174
0175
0176 int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
0177 struct xfrm_policy *xp,
0178 const struct flowi_common *flic)
0179 {
0180 u32 state_sid;
0181 u32 flic_sid;
0182
0183 if (!xp->security)
0184 if (x->security)
0185
0186 return 0;
0187 else
0188
0189 return 1;
0190 else
0191 if (!x->security)
0192
0193 return 0;
0194 else
0195 if (!selinux_authorizable_xfrm(x))
0196
0197 return 0;
0198
0199 state_sid = x->security->ctx_sid;
0200 flic_sid = flic->flowic_secid;
0201
0202 if (flic_sid != state_sid)
0203 return 0;
0204
0205
0206
0207
0208 return (avc_has_perm(&selinux_state, flic_sid, state_sid,
0209 SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
0210 NULL) ? 0 : 1);
0211 }
0212
0213 static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)
0214 {
0215 struct dst_entry *dst = skb_dst(skb);
0216 struct xfrm_state *x;
0217
0218 if (dst == NULL)
0219 return SECSID_NULL;
0220 x = dst->xfrm;
0221 if (x == NULL || !selinux_authorizable_xfrm(x))
0222 return SECSID_NULL;
0223
0224 return x->security->ctx_sid;
0225 }
0226
0227 static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb,
0228 u32 *sid, int ckall)
0229 {
0230 u32 sid_session = SECSID_NULL;
0231 struct sec_path *sp = skb_sec_path(skb);
0232
0233 if (sp) {
0234 int i;
0235
0236 for (i = sp->len - 1; i >= 0; i--) {
0237 struct xfrm_state *x = sp->xvec[i];
0238 if (selinux_authorizable_xfrm(x)) {
0239 struct xfrm_sec_ctx *ctx = x->security;
0240
0241 if (sid_session == SECSID_NULL) {
0242 sid_session = ctx->ctx_sid;
0243 if (!ckall)
0244 goto out;
0245 } else if (sid_session != ctx->ctx_sid) {
0246 *sid = SECSID_NULL;
0247 return -EINVAL;
0248 }
0249 }
0250 }
0251 }
0252
0253 out:
0254 *sid = sid_session;
0255 return 0;
0256 }
0257
0258
0259
0260
0261
0262 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
0263 {
0264 if (skb == NULL) {
0265 *sid = SECSID_NULL;
0266 return 0;
0267 }
0268 return selinux_xfrm_skb_sid_ingress(skb, sid, ckall);
0269 }
0270
0271 int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
0272 {
0273 int rc;
0274
0275 rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0);
0276 if (rc == 0 && *sid == SECSID_NULL)
0277 *sid = selinux_xfrm_skb_sid_egress(skb);
0278
0279 return rc;
0280 }
0281
0282
0283
0284
0285 int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
0286 struct xfrm_user_sec_ctx *uctx,
0287 gfp_t gfp)
0288 {
0289 return selinux_xfrm_alloc_user(ctxp, uctx, gfp);
0290 }
0291
0292
0293
0294
0295
0296 int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
0297 struct xfrm_sec_ctx **new_ctxp)
0298 {
0299 struct xfrm_sec_ctx *new_ctx;
0300
0301 if (!old_ctx)
0302 return 0;
0303
0304 new_ctx = kmemdup(old_ctx, sizeof(*old_ctx) + old_ctx->ctx_len,
0305 GFP_ATOMIC);
0306 if (!new_ctx)
0307 return -ENOMEM;
0308 atomic_inc(&selinux_xfrm_refcount);
0309 *new_ctxp = new_ctx;
0310
0311 return 0;
0312 }
0313
0314
0315
0316
0317 void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
0318 {
0319 selinux_xfrm_free(ctx);
0320 }
0321
0322
0323
0324
0325 int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
0326 {
0327 return selinux_xfrm_delete(ctx);
0328 }
0329
0330
0331
0332
0333
0334 int selinux_xfrm_state_alloc(struct xfrm_state *x,
0335 struct xfrm_user_sec_ctx *uctx)
0336 {
0337 return selinux_xfrm_alloc_user(&x->security, uctx, GFP_KERNEL);
0338 }
0339
0340
0341
0342
0343
0344 int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
0345 struct xfrm_sec_ctx *polsec, u32 secid)
0346 {
0347 int rc;
0348 struct xfrm_sec_ctx *ctx;
0349 char *ctx_str = NULL;
0350 u32 str_len;
0351
0352 if (!polsec)
0353 return 0;
0354
0355 if (secid == 0)
0356 return -EINVAL;
0357
0358 rc = security_sid_to_context(&selinux_state, secid, &ctx_str,
0359 &str_len);
0360 if (rc)
0361 return rc;
0362
0363 ctx = kmalloc(struct_size(ctx, ctx_str, str_len), GFP_ATOMIC);
0364 if (!ctx) {
0365 rc = -ENOMEM;
0366 goto out;
0367 }
0368
0369 ctx->ctx_doi = XFRM_SC_DOI_LSM;
0370 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
0371 ctx->ctx_sid = secid;
0372 ctx->ctx_len = str_len;
0373 memcpy(ctx->ctx_str, ctx_str, str_len);
0374
0375 x->security = ctx;
0376 atomic_inc(&selinux_xfrm_refcount);
0377 out:
0378 kfree(ctx_str);
0379 return rc;
0380 }
0381
0382
0383
0384
0385 void selinux_xfrm_state_free(struct xfrm_state *x)
0386 {
0387 selinux_xfrm_free(x->security);
0388 }
0389
0390
0391
0392
0393 int selinux_xfrm_state_delete(struct xfrm_state *x)
0394 {
0395 return selinux_xfrm_delete(x->security);
0396 }
0397
0398
0399
0400
0401
0402
0403
0404
0405 int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
0406 struct common_audit_data *ad)
0407 {
0408 int i;
0409 struct sec_path *sp = skb_sec_path(skb);
0410 u32 peer_sid = SECINITSID_UNLABELED;
0411
0412 if (sp) {
0413 for (i = 0; i < sp->len; i++) {
0414 struct xfrm_state *x = sp->xvec[i];
0415
0416 if (x && selinux_authorizable_xfrm(x)) {
0417 struct xfrm_sec_ctx *ctx = x->security;
0418 peer_sid = ctx->ctx_sid;
0419 break;
0420 }
0421 }
0422 }
0423
0424
0425
0426
0427 return avc_has_perm(&selinux_state,
0428 sk_sid, peer_sid,
0429 SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439 int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
0440 struct common_audit_data *ad, u8 proto)
0441 {
0442 struct dst_entry *dst;
0443
0444 switch (proto) {
0445 case IPPROTO_AH:
0446 case IPPROTO_ESP:
0447 case IPPROTO_COMP:
0448
0449
0450
0451 return 0;
0452 default:
0453 break;
0454 }
0455
0456 dst = skb_dst(skb);
0457 if (dst) {
0458 struct dst_entry *iter;
0459
0460 for (iter = dst; iter != NULL; iter = xfrm_dst_child(iter)) {
0461 struct xfrm_state *x = iter->xfrm;
0462
0463 if (x && selinux_authorizable_xfrm(x))
0464 return 0;
0465 }
0466 }
0467
0468
0469
0470
0471 return avc_has_perm(&selinux_state, sk_sid, SECINITSID_UNLABELED,
0472 SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
0473 }