X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=security%2Fselinux%2Fxfrm.c;h=8f17f542a1160bc44ccff63f8a0fe07e756e86b5;hb=0f4238958d28044b335644b69df6071cdb04b5ce;hp=36a191e7004e957fb38de4e9c5507f8941a33062;hpb=1212663fba7c5e003e05d24f043d5ed57eb18b24;p=linux-2.6-omap-h63xx.git diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 36a191e7004..8f17f542a11 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -45,12 +45,14 @@ #include #include #include -#include +#include #include "avc.h" #include "objsec.h" #include "xfrm.h" +/* Labeled XFRM instance counter */ +atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0); /* * Returns true if an LSM/SELinux context @@ -74,20 +76,18 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x) * LSM hook implementation that authorizes that a flow can use * a xfrm policy rule. */ -int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) +int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir) { int rc; u32 sel_sid; - struct xfrm_sec_ctx *ctx; /* Context sid is either set to label or ANY_ASSOC */ - if ((ctx = xp->security)) { + if (ctx) { if (!selinux_authorizable_ctx(ctx)) return -EINVAL; sel_sid = ctx->ctx_sid; - } - else + } else /* * All flows should be treated as polmatch'ing an * otherwise applicable "non-labeled" policy. This @@ -100,7 +100,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) NULL); if (rc == -EACCES) - rc = -ESRCH; + return -ESRCH; return rc; } @@ -180,8 +180,7 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) if (!ckall) break; - } - else if (*sid != ctx->ctx_sid) + } else if (*sid != ctx->ctx_sid) return -EINVAL; } } @@ -211,26 +210,27 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX) return -EINVAL; - if (uctx->ctx_len >= PAGE_SIZE) + str_len = uctx->ctx_len; + if (str_len >= PAGE_SIZE) return -ENOMEM; *ctxp = ctx = kmalloc(sizeof(*ctx) + - uctx->ctx_len + 1, + str_len + 1, GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->ctx_doi = uctx->ctx_doi; - ctx->ctx_len = uctx->ctx_len; + ctx->ctx_len = str_len; ctx->ctx_alg = uctx->ctx_alg; memcpy(ctx->ctx_str, uctx+1, - ctx->ctx_len); - ctx->ctx_str[ctx->ctx_len] = 0; + str_len); + ctx->ctx_str[str_len] = 0; rc = security_context_to_sid(ctx->ctx_str, - ctx->ctx_len, + str_len, &ctx->ctx_sid); if (rc) @@ -283,15 +283,17 @@ out2: * LSM hook implementation that allocs and transfers uctx spec to * xfrm_policy. */ -int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, - struct xfrm_user_sec_ctx *uctx) +int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, + struct xfrm_user_sec_ctx *uctx) { int err; - BUG_ON(!xp); BUG_ON(!uctx); - err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0); + err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0); + if (err == 0) + atomic_inc(&selinux_xfrm_refcount); + return err; } @@ -300,49 +302,47 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, * LSM hook implementation that copies security data structure from old to * new for policy cloning. */ -int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) +int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, + struct xfrm_sec_ctx **new_ctxp) { - struct xfrm_sec_ctx *old_ctx, *new_ctx; - - old_ctx = old->security; + struct xfrm_sec_ctx *new_ctx; if (old_ctx) { - new_ctx = new->security = kmalloc(sizeof(*new_ctx) + - old_ctx->ctx_len, - GFP_KERNEL); - + new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len, + GFP_KERNEL); if (!new_ctx) return -ENOMEM; memcpy(new_ctx, old_ctx, sizeof(*new_ctx)); memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len); + *new_ctxp = new_ctx; } return 0; } /* - * LSM hook implementation that frees xfrm_policy security information. + * LSM hook implementation that frees xfrm_sec_ctx security information. */ -void selinux_xfrm_policy_free(struct xfrm_policy *xp) +void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx) { - struct xfrm_sec_ctx *ctx = xp->security; - if (ctx) - kfree(ctx); + kfree(ctx); } /* * LSM hook implementation that authorizes deletion of labeled policies. */ -int selinux_xfrm_policy_delete(struct xfrm_policy *xp) +int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) { struct task_security_struct *tsec = current->security; - struct xfrm_sec_ctx *ctx = xp->security; int rc = 0; - if (ctx) + if (ctx) { rc = avc_has_perm(tsec->sid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); + if (rc == 0) + atomic_dec(&selinux_xfrm_refcount); + } return rc; } @@ -359,6 +359,8 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct BUG_ON(!x); err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid); + if (err == 0) + atomic_inc(&selinux_xfrm_refcount); return err; } @@ -368,8 +370,7 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct void selinux_xfrm_state_free(struct xfrm_state *x) { struct xfrm_sec_ctx *ctx = x->security; - if (ctx) - kfree(ctx); + kfree(ctx); } /* @@ -381,10 +382,13 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) struct xfrm_sec_ctx *ctx = x->security; int rc = 0; - if (ctx) + if (ctx) { rc = avc_has_perm(tsec->sid, ctx->ctx_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL); + if (rc == 0) + atomic_dec(&selinux_xfrm_refcount); + } return rc; }