summaryrefslogtreecommitdiff
path: root/security/selinux/xfrm.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/xfrm.c')
-rw-r--r--security/selinux/xfrm.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 36a191e7004e..7e158205d081 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -46,11 +46,14 @@
#include <net/checksum.h>
#include <net/udp.h>
#include <asm/semaphore.h>
+#include <asm/atomic.h>
#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
@@ -211,26 +214,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)
@@ -292,6 +296,9 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
BUG_ON(!uctx);
err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
+ if (err == 0)
+ atomic_inc(&selinux_xfrm_refcount);
+
return err;
}
@@ -339,10 +346,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
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 +369,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;
}
@@ -381,10 +393,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;
}