Skip to content

Commit

Permalink
SELinux: Various xfrm labeling fixes
Browse files Browse the repository at this point in the history
Since the upstreaming of the mlsxfrm modification a few months back,
testing has resulted in the identification of the following issues/bugs that
are resolved in this patch set.

1. Fix the security context used in the IKE negotiation to be the context
   of the socket as opposed to the context of the SPD rule.

2. Fix SO_PEERSEC for tcp sockets to return the security context of
   the peer as opposed to the source.

3. Fix the selection of an SA for an outgoing packet to be at the same
   context as the originating socket/flow.

The following would be the result of applying this patchset:

- SO_PEERSEC will now correctly return the peer's context.

- IKE deamons will receive the context of the source socket/flow
  as opposed to the SPD rule's context so that the negotiated SA
  will be at the same context as the source socket/flow.

- The SELinux policy will require one or more of the
  following for a socket to be able to communicate with/without SAs:

  1. To enable a socket to communicate without using labeled-IPSec SAs:

     allow socket_t unlabeled_t:association { sendto recvfrom }

  2. To enable a socket to communicate with labeled-IPSec SAs:

     allow socket_t self:association { sendto };
     allow socket_t peer_sa_t:association { recvfrom };

This Patch: Pass correct security context to IKE for use in negotiation

Fix the security context passed to IKE for use in negotiation to be the
context of the socket as opposed to the context of the SPD rule so that
the SA carries the label of the originating socket/flow.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
Signed-off-by: James Morris <jmorris@namei.org>
  • Loading branch information
Venkat Yekkirala authored and David S. Miller committed Dec 3, 2006
1 parent e8db8c9 commit c1a856c
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 41 deletions.
21 changes: 10 additions & 11 deletions include/linux/security.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,10 +836,8 @@ struct request_sock;
* used by the XFRM system.
* @sec_ctx contains the security context information being provided by
* the user-level policy update program (e.g., setkey).
* @sk refers to the sock from which to derive the security context.
* Allocate a security structure to the xp->security field; the security
* field is initialized to NULL when the xfrm_policy is allocated. Only
* one of sec_ctx or sock can be specified.
* field is initialized to NULL when the xfrm_policy is allocated.
* Return 0 if operation was successful (memory to allocate, legal context)
* @xfrm_policy_clone_security:
* @old contains an existing xfrm_policy in the SPD.
Expand All @@ -858,9 +856,6 @@ struct request_sock;
* Database by the XFRM system.
* @sec_ctx contains the security context information being provided by
* the user-level SA generation program (e.g., setkey or racoon).
* @polsec contains the security context information associated with a xfrm
* policy rule from which to take the base context. polsec must be NULL
* when sec_ctx is specified.
* @secid contains the secid from which to take the mls portion of the context.
* Allocate a security structure to the x->security field; the security
* field is initialized to NULL when the xfrm_state is allocated. Set the
Expand Down Expand Up @@ -1378,12 +1373,12 @@ struct security_operations {

#ifdef CONFIG_SECURITY_NETWORK_XFRM
int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk);
struct xfrm_user_sec_ctx *sec_ctx);
int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
int (*xfrm_state_alloc_security) (struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *polsec,
struct xfrm_user_sec_ctx *sec_ctx,
u32 secid);
void (*xfrm_state_free_security) (struct xfrm_state *x);
int (*xfrm_state_delete_security) (struct xfrm_state *x);
Expand Down Expand Up @@ -3120,7 +3115,7 @@ static inline void security_inet_csk_clone(struct sock *newsk,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
{
return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL);
return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
}

static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
Expand All @@ -3141,15 +3136,19 @@ static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
static inline int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
return security_ops->xfrm_state_alloc_security(x, sec_ctx, NULL, 0);
return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
}

static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid)
{
if (!polsec)
return 0;
return security_ops->xfrm_state_alloc_security(x, NULL, polsec, secid);
/*
* We want the context to be taken from secid which is usually
* from the sock.
*/
return security_ops->xfrm_state_alloc_security(x, NULL, secid);
}

static inline int security_xfrm_state_delete(struct xfrm_state *x)
Expand Down
4 changes: 2 additions & 2 deletions security/dummy.c
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,

#ifdef CONFIG_SECURITY_NETWORK_XFRM
static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk)
struct xfrm_user_sec_ctx *sec_ctx)
{
return 0;
}
Expand All @@ -856,7 +856,7 @@ static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
}

static int dummy_xfrm_state_alloc_security(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid)
struct xfrm_user_sec_ctx *sec_ctx, u32 secid)
{
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions security/selinux/include/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
#define _SELINUX_XFRM_H_

int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk);
struct xfrm_user_sec_ctx *sec_ctx);
int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
void selinux_xfrm_policy_free(struct xfrm_policy *xp);
int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
int selinux_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid);
struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
void selinux_xfrm_state_free(struct xfrm_state *x);
int selinux_xfrm_state_delete(struct xfrm_state *x);
int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
Expand Down
35 changes: 9 additions & 26 deletions security/selinux/xfrm.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,16 +226,15 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
* 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, struct xfrm_sec_ctx *pol, u32 sid)
struct xfrm_user_sec_ctx *uctx, u32 sid)
{
int rc = 0;
struct task_security_struct *tsec = current->security;
struct xfrm_sec_ctx *ctx = NULL;
char *ctx_str = NULL;
u32 str_len;
u32 ctx_sid;

BUG_ON(uctx && pol);
BUG_ON(uctx && sid);

if (!uctx)
goto not_from_user;
Expand Down Expand Up @@ -279,15 +278,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
return rc;

not_from_user:
if (pol) {
rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid);
if (rc)
goto out;
}
else
ctx_sid = sid;

rc = security_sid_to_context(ctx_sid, &ctx_str, &str_len);
rc = security_sid_to_context(sid, &ctx_str, &str_len);
if (rc)
goto out;

Expand All @@ -302,7 +293,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,

ctx->ctx_doi = XFRM_SC_DOI_LSM;
ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
ctx->ctx_sid = ctx_sid;
ctx->ctx_sid = sid;
ctx->ctx_len = str_len;
memcpy(ctx->ctx_str,
ctx_str,
Expand All @@ -323,22 +314,14 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
* xfrm_policy.
*/
int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
struct xfrm_user_sec_ctx *uctx, struct sock *sk)
struct xfrm_user_sec_ctx *uctx)
{
int err;
u32 sid;

BUG_ON(!xp);
BUG_ON(uctx && sk);

if (sk) {
struct sk_security_struct *ssec = sk->sk_security;
sid = ssec->sid;
}
else
sid = SECSID_NULL;
BUG_ON(!uctx);

err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, NULL, sid);
err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
return err;
}

Expand Down Expand Up @@ -399,13 +382,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
* xfrm_state.
*/
int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
struct xfrm_sec_ctx *pol, u32 secid)
u32 secid)
{
int err;

BUG_ON(!x);

err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, pol, secid);
err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
return err;
}

Expand Down

0 comments on commit c1a856c

Please sign in to comment.