|
@@ -56,7 +56,7 @@
|
|
|
atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
|
|
|
|
|
|
/*
|
|
|
- * Returns true if an LSM/SELinux context
|
|
|
+ * Returns true if the context is an LSM/SELinux context.
|
|
|
*/
|
|
|
static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
|
|
|
{
|
|
@@ -66,7 +66,7 @@ static inline int selinux_authorizable_ctx(struct xfrm_sec_ctx *ctx)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Returns true if the xfrm contains a security blob for SELinux
|
|
|
+ * Returns true if the xfrm contains a security blob for SELinux.
|
|
|
*/
|
|
|
static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
|
|
|
{
|
|
@@ -74,48 +74,111 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * LSM hook implementation that authorizes that a flow can use
|
|
|
- * a xfrm policy rule.
|
|
|
+ * Allocates a xfrm_sec_state and populates it using the supplied security
|
|
|
+ * xfrm_user_sec_ctx context.
|
|
|
*/
|
|
|
-int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
|
|
|
+static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
|
|
|
+ struct xfrm_user_sec_ctx *uctx)
|
|
|
{
|
|
|
int rc;
|
|
|
- u32 sel_sid;
|
|
|
+ const struct task_security_struct *tsec = current_security();
|
|
|
+ struct xfrm_sec_ctx *ctx = NULL;
|
|
|
+ u32 str_len;
|
|
|
|
|
|
- /* Context sid is either set to label or ANY_ASSOC */
|
|
|
- if (ctx) {
|
|
|
- if (!selinux_authorizable_ctx(ctx))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- sel_sid = ctx->ctx_sid;
|
|
|
- } else
|
|
|
- /*
|
|
|
- * All flows should be treated as polmatch'ing an
|
|
|
- * otherwise applicable "non-labeled" policy. This
|
|
|
- * would prevent inadvertent "leaks".
|
|
|
- */
|
|
|
- return 0;
|
|
|
+ if (ctxp == NULL || uctx == NULL ||
|
|
|
+ uctx->ctx_doi != XFRM_SC_DOI_LSM ||
|
|
|
+ uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
|
|
|
- ASSOCIATION__POLMATCH,
|
|
|
- NULL);
|
|
|
+ str_len = uctx->ctx_len;
|
|
|
+ if (str_len >= PAGE_SIZE)
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
- if (rc == -EACCES)
|
|
|
- return -ESRCH;
|
|
|
+ ctx = kmalloc(sizeof(*ctx) + str_len + 1, GFP_KERNEL);
|
|
|
+ if (!ctx)
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
+ ctx->ctx_doi = XFRM_SC_DOI_LSM;
|
|
|
+ ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
|
|
|
+ ctx->ctx_len = str_len;
|
|
|
+ memcpy(ctx->ctx_str, &uctx[1], str_len);
|
|
|
+ ctx->ctx_str[str_len] = '\0';
|
|
|
+ rc = security_context_to_sid(ctx->ctx_str, str_len, &ctx->ctx_sid);
|
|
|
+ if (rc)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
|
|
|
+ SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, NULL);
|
|
|
+ if (rc)
|
|
|
+ goto err;
|
|
|
+
|
|
|
+ *ctxp = ctx;
|
|
|
+ atomic_inc(&selinux_xfrm_refcount);
|
|
|
+ return 0;
|
|
|
+
|
|
|
+err:
|
|
|
+ kfree(ctx);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Free the xfrm_sec_ctx structure.
|
|
|
+ */
|
|
|
+static void selinux_xfrm_free(struct xfrm_sec_ctx *ctx)
|
|
|
+{
|
|
|
+ if (!ctx)
|
|
|
+ return;
|
|
|
+
|
|
|
+ atomic_dec(&selinux_xfrm_refcount);
|
|
|
+ kfree(ctx);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Authorize the deletion of a labeled SA or policy rule.
|
|
|
+ */
|
|
|
+static int selinux_xfrm_delete(struct xfrm_sec_ctx *ctx)
|
|
|
+{
|
|
|
+ const struct task_security_struct *tsec = current_security();
|
|
|
+
|
|
|
+ if (!ctx)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return avc_has_perm(tsec->sid, ctx->ctx_sid,
|
|
|
+ SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
|
|
|
+ NULL);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * LSM hook implementation that authorizes that a flow can use a xfrm policy
|
|
|
+ * rule.
|
|
|
+ */
|
|
|
+int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+
|
|
|
+ /* All flows should be treated as polmatch'ing an otherwise applicable
|
|
|
+ * "non-labeled" policy. This would prevent inadvertent "leaks". */
|
|
|
+ if (!ctx)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ /* Context sid is either set to label or ANY_ASSOC */
|
|
|
+ if (!selinux_authorizable_ctx(ctx))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ rc = avc_has_perm(fl_secid, ctx->ctx_sid,
|
|
|
+ SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, NULL);
|
|
|
+ return (rc == -EACCES ? -ESRCH : rc);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* LSM hook implementation that authorizes that a state matches
|
|
|
* the given policy, flow combo.
|
|
|
*/
|
|
|
-
|
|
|
-int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp,
|
|
|
- const struct flowi *fl)
|
|
|
+int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
|
|
|
+ struct xfrm_policy *xp,
|
|
|
+ const struct flowi *fl)
|
|
|
{
|
|
|
u32 state_sid;
|
|
|
- int rc;
|
|
|
|
|
|
if (!xp->security)
|
|
|
if (x->security)
|
|
@@ -138,187 +201,80 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
|
|
|
if (fl->flowi_secid != state_sid)
|
|
|
return 0;
|
|
|
|
|
|
- rc = avc_has_perm(fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION,
|
|
|
- ASSOCIATION__SENDTO,
|
|
|
- NULL)? 0:1;
|
|
|
-
|
|
|
- /*
|
|
|
- * We don't need a separate SA Vs. policy polmatch check
|
|
|
- * since the SA is now of the same label as the flow and
|
|
|
- * a flow Vs. policy polmatch check had already happened
|
|
|
- * in selinux_xfrm_policy_lookup() above.
|
|
|
- */
|
|
|
-
|
|
|
- return rc;
|
|
|
+ /* We don't need a separate SA Vs. policy polmatch check since the SA
|
|
|
+ * is now of the same label as the flow and a flow Vs. policy polmatch
|
|
|
+ * check had already happened in selinux_xfrm_policy_lookup() above. */
|
|
|
+ return (avc_has_perm(fl->flowi_secid, state_sid,
|
|
|
+ SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
|
|
|
+ NULL) ? 0 : 1);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* LSM hook implementation that checks and/or returns the xfrm sid for the
|
|
|
* incoming packet.
|
|
|
*/
|
|
|
-
|
|
|
int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
|
|
|
{
|
|
|
+ u32 sid_session = SECSID_NULL;
|
|
|
struct sec_path *sp;
|
|
|
|
|
|
- *sid = SECSID_NULL;
|
|
|
-
|
|
|
if (skb == NULL)
|
|
|
- return 0;
|
|
|
+ goto out;
|
|
|
|
|
|
sp = skb->sp;
|
|
|
if (sp) {
|
|
|
- int i, sid_set = 0;
|
|
|
+ int i;
|
|
|
|
|
|
- for (i = sp->len-1; i >= 0; i--) {
|
|
|
+ for (i = sp->len - 1; i >= 0; i--) {
|
|
|
struct xfrm_state *x = sp->xvec[i];
|
|
|
if (selinux_authorizable_xfrm(x)) {
|
|
|
struct xfrm_sec_ctx *ctx = x->security;
|
|
|
|
|
|
- if (!sid_set) {
|
|
|
- *sid = ctx->ctx_sid;
|
|
|
- sid_set = 1;
|
|
|
-
|
|
|
+ if (sid_session == SECSID_NULL) {
|
|
|
+ sid_session = ctx->ctx_sid;
|
|
|
if (!ckall)
|
|
|
- break;
|
|
|
- } else if (*sid != ctx->ctx_sid)
|
|
|
+ goto out;
|
|
|
+ } else if (sid_session != ctx->ctx_sid) {
|
|
|
+ *sid = SECSID_NULL;
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * Security blob allocation for xfrm_policy and xfrm_state
|
|
|
- * CTX does not have a meaningful value on input
|
|
|
- */
|
|
|
-static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
|
|
|
- struct xfrm_user_sec_ctx *uctx, u32 sid)
|
|
|
-{
|
|
|
- int rc = 0;
|
|
|
- const struct task_security_struct *tsec = current_security();
|
|
|
- struct xfrm_sec_ctx *ctx = NULL;
|
|
|
- char *ctx_str = NULL;
|
|
|
- u32 str_len;
|
|
|
-
|
|
|
- BUG_ON(uctx && sid);
|
|
|
-
|
|
|
- if (!uctx)
|
|
|
- goto not_from_user;
|
|
|
-
|
|
|
- if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- str_len = uctx->ctx_len;
|
|
|
- if (str_len >= PAGE_SIZE)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- *ctxp = ctx = kmalloc(sizeof(*ctx) +
|
|
|
- str_len + 1,
|
|
|
- GFP_KERNEL);
|
|
|
-
|
|
|
- if (!ctx)
|
|
|
- return -ENOMEM;
|
|
|
-
|
|
|
- ctx->ctx_doi = uctx->ctx_doi;
|
|
|
- ctx->ctx_len = str_len;
|
|
|
- ctx->ctx_alg = uctx->ctx_alg;
|
|
|
-
|
|
|
- memcpy(ctx->ctx_str,
|
|
|
- uctx+1,
|
|
|
- str_len);
|
|
|
- ctx->ctx_str[str_len] = 0;
|
|
|
- rc = security_context_to_sid(ctx->ctx_str,
|
|
|
- str_len,
|
|
|
- &ctx->ctx_sid);
|
|
|
-
|
|
|
- if (rc)
|
|
|
- goto out;
|
|
|
-
|
|
|
- /*
|
|
|
- * Does the subject have permission to set security context?
|
|
|
- */
|
|
|
- rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
|
|
|
- SECCLASS_ASSOCIATION,
|
|
|
- ASSOCIATION__SETCONTEXT, NULL);
|
|
|
- if (rc)
|
|
|
- goto out;
|
|
|
-
|
|
|
- return rc;
|
|
|
-
|
|
|
-not_from_user:
|
|
|
- rc = security_sid_to_context(sid, &ctx_str, &str_len);
|
|
|
- if (rc)
|
|
|
- goto out;
|
|
|
-
|
|
|
- *ctxp = ctx = kmalloc(sizeof(*ctx) +
|
|
|
- str_len,
|
|
|
- GFP_ATOMIC);
|
|
|
-
|
|
|
- if (!ctx) {
|
|
|
- rc = -ENOMEM;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- ctx->ctx_doi = XFRM_SC_DOI_LSM;
|
|
|
- ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
|
|
|
- ctx->ctx_sid = sid;
|
|
|
- ctx->ctx_len = str_len;
|
|
|
- memcpy(ctx->ctx_str,
|
|
|
- ctx_str,
|
|
|
- str_len);
|
|
|
-
|
|
|
- goto out2;
|
|
|
-
|
|
|
out:
|
|
|
- *ctxp = NULL;
|
|
|
- kfree(ctx);
|
|
|
-out2:
|
|
|
- kfree(ctx_str);
|
|
|
- return rc;
|
|
|
+ *sid = sid_session;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * LSM hook implementation that allocs and transfers uctx spec to
|
|
|
- * xfrm_policy.
|
|
|
+ * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
|
|
|
*/
|
|
|
int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
|
|
|
struct xfrm_user_sec_ctx *uctx)
|
|
|
{
|
|
|
- int err;
|
|
|
-
|
|
|
- BUG_ON(!uctx);
|
|
|
-
|
|
|
- err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
|
|
|
- if (err == 0)
|
|
|
- atomic_inc(&selinux_xfrm_refcount);
|
|
|
-
|
|
|
- return err;
|
|
|
+ return selinux_xfrm_alloc_user(ctxp, uctx);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/*
|
|
|
- * LSM hook implementation that copies security data structure from old to
|
|
|
- * new for policy cloning.
|
|
|
+ * LSM hook implementation that copies security data structure from old to new
|
|
|
+ * for policy cloning.
|
|
|
*/
|
|
|
int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
|
|
|
struct xfrm_sec_ctx **new_ctxp)
|
|
|
{
|
|
|
struct xfrm_sec_ctx *new_ctx;
|
|
|
|
|
|
- if (old_ctx) {
|
|
|
- new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
|
|
|
- GFP_ATOMIC);
|
|
|
- if (!new_ctx)
|
|
|
- return -ENOMEM;
|
|
|
+ if (!old_ctx)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len, GFP_ATOMIC);
|
|
|
+ if (!new_ctx)
|
|
|
+ return -ENOMEM;
|
|
|
+ memcpy(new_ctx, old_ctx, sizeof(*old_ctx) + old_ctx->ctx_len);
|
|
|
+ atomic_inc(&selinux_xfrm_refcount);
|
|
|
+ *new_ctxp = new_ctx;
|
|
|
|
|
|
- memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
|
|
|
- memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
|
|
|
- atomic_inc(&selinux_xfrm_refcount);
|
|
|
- *new_ctxp = new_ctx;
|
|
|
- }
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -327,8 +283,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
|
|
|
*/
|
|
|
void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
|
|
|
{
|
|
|
- atomic_dec(&selinux_xfrm_refcount);
|
|
|
- kfree(ctx);
|
|
|
+ selinux_xfrm_free(ctx);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -336,31 +291,55 @@ void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
|
|
|
*/
|
|
|
int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
|
|
|
{
|
|
|
- const struct task_security_struct *tsec = current_security();
|
|
|
-
|
|
|
- if (!ctx)
|
|
|
- return 0;
|
|
|
+ return selinux_xfrm_delete(ctx);
|
|
|
+}
|
|
|
|
|
|
- return avc_has_perm(tsec->sid, ctx->ctx_sid,
|
|
|
- SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
|
|
|
- NULL);
|
|
|
+/*
|
|
|
+ * LSM hook implementation that allocates a xfrm_sec_state, populates it using
|
|
|
+ * the supplied security context, and assigns it to the xfrm_state.
|
|
|
+ */
|
|
|
+int selinux_xfrm_state_alloc(struct xfrm_state *x,
|
|
|
+ struct xfrm_user_sec_ctx *uctx)
|
|
|
+{
|
|
|
+ return selinux_xfrm_alloc_user(&x->security, uctx);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * LSM hook implementation that allocs and transfers sec_ctx spec to
|
|
|
- * xfrm_state.
|
|
|
+ * LSM hook implementation that allocates a xfrm_sec_state and populates based
|
|
|
+ * on a secid.
|
|
|
*/
|
|
|
-int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
|
|
|
- u32 secid)
|
|
|
+int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
|
|
|
+ struct xfrm_sec_ctx *polsec, u32 secid)
|
|
|
{
|
|
|
- int err;
|
|
|
+ int rc;
|
|
|
+ struct xfrm_sec_ctx *ctx;
|
|
|
+ char *ctx_str = NULL;
|
|
|
+ int str_len;
|
|
|
+
|
|
|
+ if (!polsec)
|
|
|
+ return 0;
|
|
|
|
|
|
- BUG_ON(!x);
|
|
|
+ if (secid == 0)
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
- err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
|
|
|
- if (err == 0)
|
|
|
- atomic_inc(&selinux_xfrm_refcount);
|
|
|
- return err;
|
|
|
+ rc = security_sid_to_context(secid, &ctx_str, &str_len);
|
|
|
+ if (rc)
|
|
|
+ return rc;
|
|
|
+
|
|
|
+ ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
|
|
|
+ if (!ctx)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ ctx->ctx_doi = XFRM_SC_DOI_LSM;
|
|
|
+ ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
|
|
|
+ ctx->ctx_sid = secid;
|
|
|
+ ctx->ctx_len = str_len;
|
|
|
+ memcpy(ctx->ctx_str, ctx_str, str_len);
|
|
|
+ kfree(ctx_str);
|
|
|
+
|
|
|
+ x->security = ctx;
|
|
|
+ atomic_inc(&selinux_xfrm_refcount);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -368,24 +347,15 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
|
|
|
*/
|
|
|
void selinux_xfrm_state_free(struct xfrm_state *x)
|
|
|
{
|
|
|
- atomic_dec(&selinux_xfrm_refcount);
|
|
|
- kfree(x->security);
|
|
|
+ selinux_xfrm_free(x->security);
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * LSM hook implementation that authorizes deletion of labeled SAs.
|
|
|
- */
|
|
|
+/*
|
|
|
+ * LSM hook implementation that authorizes deletion of labeled SAs.
|
|
|
+ */
|
|
|
int selinux_xfrm_state_delete(struct xfrm_state *x)
|
|
|
{
|
|
|
- const struct task_security_struct *tsec = current_security();
|
|
|
- struct xfrm_sec_ctx *ctx = x->security;
|
|
|
-
|
|
|
- if (!ctx)
|
|
|
- return 0;
|
|
|
-
|
|
|
- return avc_has_perm(tsec->sid, ctx->ctx_sid,
|
|
|
- SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT,
|
|
|
- NULL);
|
|
|
+ return selinux_xfrm_delete(x->security);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -395,14 +365,12 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
|
|
|
* we need to check for unlabelled access since this may not have
|
|
|
* gone thru the IPSec process.
|
|
|
*/
|
|
|
-int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
|
|
|
- struct common_audit_data *ad)
|
|
|
+int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
|
|
|
+ struct common_audit_data *ad)
|
|
|
{
|
|
|
- int i, rc = 0;
|
|
|
- struct sec_path *sp;
|
|
|
- u32 sel_sid = SECINITSID_UNLABELED;
|
|
|
-
|
|
|
- sp = skb->sp;
|
|
|
+ int i;
|
|
|
+ struct sec_path *sp = skb->sp;
|
|
|
+ u32 peer_sid = SECINITSID_UNLABELED;
|
|
|
|
|
|
if (sp) {
|
|
|
for (i = 0; i < sp->len; i++) {
|
|
@@ -410,23 +378,17 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
|
|
|
|
|
|
if (x && selinux_authorizable_xfrm(x)) {
|
|
|
struct xfrm_sec_ctx *ctx = x->security;
|
|
|
- sel_sid = ctx->ctx_sid;
|
|
|
+ peer_sid = ctx->ctx_sid;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * This check even when there's no association involved is
|
|
|
- * intended, according to Trent Jaeger, to make sure a
|
|
|
- * process can't engage in non-ipsec communication unless
|
|
|
- * explicitly allowed by policy.
|
|
|
- */
|
|
|
-
|
|
|
- rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
|
|
|
- ASSOCIATION__RECVFROM, ad);
|
|
|
-
|
|
|
- return rc;
|
|
|
+ /* This check even when there's no association involved is intended,
|
|
|
+ * according to Trent Jaeger, to make sure a process can't engage in
|
|
|
+ * non-IPsec communication unless explicitly allowed by policy. */
|
|
|
+ return avc_has_perm(sk_sid, peer_sid,
|
|
|
+ SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, ad);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -436,49 +398,38 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
|
|
|
* If we do have a authorizable security association, then it has already been
|
|
|
* checked in the selinux_xfrm_state_pol_flow_match hook above.
|
|
|
*/
|
|
|
-int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
|
|
|
- struct common_audit_data *ad, u8 proto)
|
|
|
+int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
|
|
|
+ struct common_audit_data *ad, u8 proto)
|
|
|
{
|
|
|
struct dst_entry *dst;
|
|
|
- int rc = 0;
|
|
|
-
|
|
|
- dst = skb_dst(skb);
|
|
|
-
|
|
|
- if (dst) {
|
|
|
- struct dst_entry *dst_test;
|
|
|
-
|
|
|
- for (dst_test = dst; dst_test != NULL;
|
|
|
- dst_test = dst_test->child) {
|
|
|
- struct xfrm_state *x = dst_test->xfrm;
|
|
|
-
|
|
|
- if (x && selinux_authorizable_xfrm(x))
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
switch (proto) {
|
|
|
case IPPROTO_AH:
|
|
|
case IPPROTO_ESP:
|
|
|
case IPPROTO_COMP:
|
|
|
- /*
|
|
|
- * We should have already seen this packet once before
|
|
|
- * it underwent xfrm(s). No need to subject it to the
|
|
|
- * unlabeled check.
|
|
|
- */
|
|
|
- goto out;
|
|
|
+ /* We should have already seen this packet once before it
|
|
|
+ * underwent xfrm(s). No need to subject it to the unlabeled
|
|
|
+ * check. */
|
|
|
+ return 0;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * This check even when there's no association involved is
|
|
|
- * intended, according to Trent Jaeger, to make sure a
|
|
|
- * process can't engage in non-ipsec communication unless
|
|
|
- * explicitly allowed by policy.
|
|
|
- */
|
|
|
+ dst = skb_dst(skb);
|
|
|
+ if (dst) {
|
|
|
+ struct dst_entry *iter;
|
|
|
|
|
|
- rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
|
|
|
- ASSOCIATION__SENDTO, ad);
|
|
|
-out:
|
|
|
- return rc;
|
|
|
+ for (iter = dst; iter != NULL; iter = iter->child) {
|
|
|
+ struct xfrm_state *x = iter->xfrm;
|
|
|
+
|
|
|
+ if (x && selinux_authorizable_xfrm(x))
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* This check even when there's no association involved is intended,
|
|
|
+ * according to Trent Jaeger, to make sure a process can't engage in
|
|
|
+ * non-IPsec communication unless explicitly allowed by policy. */
|
|
|
+ return avc_has_perm(sk_sid, SECINITSID_UNLABELED,
|
|
|
+ SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, ad);
|
|
|
}
|