This piece (relative to lspp.41 kernel) constitutes the patchset submitted 
upstream
2 weeks back. Has the following minor changes as compared to that upstream 
version:
(WILL BREAK THIS UP AGAIN WHEN SUBMITTING UPSTREAM)

- Delete debugging statements and fix a BUG_ON in xfrm.c per Stephen's comments
- Optimized sock_copy for the non-security case as suggested by Herbert and 
James.
- Added a comment for the sid member defined in flowi.

---
include/linux/security.h                     |  116 ++++++++-
include/net/flow.h | 5 include/net/sock.h | 9 net/core/flow.c | 7 net/core/sock.c | 2 net/key/af_key.c | 22 +
net/xfrm/xfrm_policy.c                       |   28 +-
net/xfrm/xfrm_state.c                        |   12 -
net/xfrm/xfrm_user.c                         |   45 ++-
security/dummy.c                             |   28 ++
security/selinux/hooks.c                     |   34 ++
security/selinux/include/av_perm_to_string.h | 1 security/selinux/include/av_permissions.h | 1 security/selinux/include/objsec.h | 1 security/selinux/include/security.h | 2 security/selinux/include/xfrm.h | 22 +
security/selinux/ss/mls.c                    |   20 -
security/selinux/ss/mls.h                    |   20 +
security/selinux/ss/services.c               |   48 ++++
security/selinux/xfrm.c                      |  198 ++++++++++++++---
20 files changed, 498 insertions(+), 123 deletions(-)

--- linux-2.6.17.i686.vanilla/include/linux/security.h  2006-07-05 
14:36:43.000000000 -0500
+++ linux-2.6.17.i686/include/linux/security.h  2006-07-05 14:38:51.000000000 
-0500
@@ -31,6 +31,7 @@
#include <linux/msg.h>
#include <linux/sched.h>
#include <linux/key.h>
+#include <linux/xfrm.h>

struct ctl_table;

@@ -795,6 +796,8 @@ struct swap_info_struct;
 *      which is used to copy security attributes between local stream sockets.
 * @sk_free_security:
 *      Deallocate security structure.
+ * @sk_clone_security:
+ *     Clone/copy security structure.
 * @sk_getsid:
 *      Retrieve the LSM-specific sid for the sock to enable caching of network
 *      authorizations.
@@ -806,9 +809,8 @@ struct swap_info_struct;
 *      used by the XFRM system.
 *      @sec_ctx contains the security context information being provided by
 *      the user-level policy update program (e.g., setkey).
- *     Allocate a security structure to the xp->selector.security field.
- *     The security field is initialized to NULL when the xfrm_policy is
- *     allocated.
+ *     Allocate a security structure to the xp->security field; the security
+ *     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.
@@ -824,9 +826,14 @@ struct swap_info_struct;
 *      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).
- *     Allocate a security structure to the x->sel.security field.  The
- *     security field is initialized to NULL when the xfrm_state is
- *     allocated.
+ *     @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.
+ *     @sid contains the sid 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
+ *     context to correspond to either sec_ctx or polsec, with the mls portion
+ *     taken from sid in the latter case.
 *      Return 0 if operation was successful (memory to allocate, legal 
context).
 * @xfrm_state_free_security:
 *      @x contains the xfrm_state.
@@ -834,13 +841,26 @@ struct swap_info_struct;
 * @xfrm_policy_lookup:
 *      @xp contains the xfrm_policy for which the access control is being
 *      checked.
- *     @sk_sid contains the sock security label that is used to authorize
+ *     @fl_sid contains the flow security label that is used to authorize
 *      access to the policy xp.
 *      @dir contains the direction of the flow (input or output).
- *     Check permission when a sock selects a xfrm_policy for processing
+ *     Check permission when a flow selects a xfrm_policy for processing
 *      XFRMs on a packet.  The hook is called when selecting either a
 *      per-socket policy or a generic xfrm policy.
 *      Return 0 if permission is granted.
+ * @xfrm_state_pol_flow_match:
+ *     @x contains the state to match.
+ *     @xp contains the policy to check for a match.
+ *     @fl contains the flow to check for a match.
+ *     Return 1 if there is a match.
+ * @xfrm_flow_state_match:
+ *     @fl contains the flow key to match.
+ *     @xfrm points to the xfrm_state to match.
+ *     Return 1 if there is a match.
+ * @xfrm_decode_session:
+ *     @skb points to skb to decode.
+ *     @fl points to the flow key to set.
+ *     Return 0 if successful decoding.
 *
 * Security hooks affecting all Key Management operations
 *
@@ -1292,6 +1312,7 @@ struct security_operations {
        int (*socket_getpeersec_dgram) (struct sk_buff *skb, char **secdata, 
u32 *seclen);
        int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
        void (*sk_free_security) (struct sock *sk);
+       void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
        unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir);
#endif  /* CONFIG_SECURITY_NETWORK */

@@ -1299,9 +1320,15 @@ struct security_operations {
        int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, 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_state_alloc_security) (struct xfrm_state *x, struct 
xfrm_user_sec_ctx *sec_ctx);
+       int (*xfrm_state_alloc_security) (struct xfrm_state *x,
+               struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *polsec,
+               u32 sid);
        void (*xfrm_state_free_security) (struct xfrm_state *x);
-       int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
+       int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_sid, u8 dir);
+       int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
+                       struct xfrm_policy *xp, struct flowi *fl);
+       int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm);
+       int (*xfrm_decode_session)(struct sk_buff *skb, struct flowi *fl);
#endif  /* CONFIG_SECURITY_NETWORK_XFRM */

        /* key management security hooks */
@@ -2786,6 +2813,11 @@ static inline void security_sk_free(stru
        return security_ops->sk_free_security(sk);
}

+static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
+{
+       return security_ops->sk_clone_security(sk, newsk);
+}
+
static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, 
u8 dir)
{
        return security_ops->sk_getsid(sk, fl, dir);
@@ -2914,6 +2946,10 @@ static inline void security_sk_free(stru
{
}

+static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
+{
+}
+
static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, 
u8 dir)
{
        return 0;
@@ -2936,9 +2972,16 @@ static inline void security_xfrm_policy_
        security_ops->xfrm_policy_free_security(xp);
}

-static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct 
xfrm_user_sec_ctx *sec_ctx)
+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);
+}
+
+static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
+                               struct xfrm_sec_ctx *polsec, u32 sid)
{
-       return security_ops->xfrm_state_alloc_security(x, sec_ctx);
+       return security_ops->xfrm_state_alloc_security(x, NULL, polsec, sid);
}

static inline void security_xfrm_state_free(struct xfrm_state *x)
@@ -2946,9 +2989,25 @@ static inline void security_xfrm_state_f
        security_ops->xfrm_state_free_security(x);
}

-static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 
sk_sid, u8 dir)
+static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 
fl_sid, u8 dir)
+{
+       return security_ops->xfrm_policy_lookup(xp, fl_sid, dir);
+}
+
+static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+                       struct xfrm_policy *xp, struct flowi *fl)
{
-       return security_ops->xfrm_policy_lookup(xp, sk_sid, dir);
+       return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
+}
+
+static inline int security_xfrm_flow_state_match(struct flowi *fl, struct 
xfrm_state *xfrm)
+{
+       return security_ops->xfrm_flow_state_match(fl, xfrm);
+}
+
+static inline int security_xfrm_decode_session(struct sk_buff *skb, struct 
flowi *fl)
+{
+       return security_ops->xfrm_decode_session(skb, fl);
}
#else   /* CONFIG_SECURITY_NETWORK_XFRM */
static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct 
xfrm_user_sec_ctx *sec_ctx)
@@ -2965,7 +3024,14 @@ static inline void security_xfrm_policy_
{
}

-static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct 
xfrm_user_sec_ctx *sec_ctx)
+static inline int security_xfrm_state_alloc(struct xfrm_state *x,
+                                       struct xfrm_user_sec_ctx *sec_ctx)
+{
+       return 0;
+}
+
+static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
+                                       struct xfrm_sec_ctx *polsec, u32 sid)
{
        return 0;
}
@@ -2974,10 +3040,28 @@ static inline void security_xfrm_state_f
{
}

-static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 
sk_sid, u8 dir)
+static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 
fl_sid, u8 dir)
{
        return 0;
}
+
+static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
+                       struct xfrm_policy *xp, struct flowi *fl)
+{
+       return 1;
+}
+
+static inline int security_xfrm_flow_state_match(struct flowi *fl,
+                                struct xfrm_state *xfrm)
+{
+       return 1;
+}
+
+static inline int security_xfrm_decode_session(struct sk_buff *skb, struct 
flowi *fl)
+{
+       return 0;
+}
+
#endif  /* CONFIG_SECURITY_NETWORK_XFRM */

#ifdef CONFIG_KEYS
--- linux-2.6.17.i686.vanilla/include/net/flow.h        2006-06-17 
20:49:35.000000000 -0500
+++ linux-2.6.17.i686/include/net/flow.h        2006-07-05 14:38:51.000000000 
-0500
@@ -78,6 +78,7 @@ struct flowi {
#define fl_icmp_type    uli_u.icmpt.type
#define fl_icmp_code    uli_u.icmpt.code
#define fl_ipsec_spi    uli_u.spi
+       __u32           sid;    /* used by xfrm; see flow_sid.txt */
} __attribute__((__aligned__(BITS_PER_LONG/8)));

#define FLOW_DIR_IN     0
@@ -85,10 +86,10 @@ struct flowi {
#define FLOW_DIR_FWD    2

struct sock;
-typedef void (*flow_resolve_t)(struct flowi *key, u32 sk_sid, u16 family, u8 
dir,
+typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
                               void **objp, atomic_t **obj_refp);

-extern void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 
dir,
+extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
                               flow_resolve_t resolver);
extern void flow_cache_flush(void);
extern atomic_t flow_cache_genid;
--- linux-2.6.17.i686.vanilla/include/net/sock.h        2006-07-05 
14:36:37.000000000 -0500
+++ linux-2.6.17.i686/include/net/sock.h        2006-07-05 14:38:51.000000000 
-0500
@@ -968,6 +968,15 @@ static inline void sock_graft(struct soc
        write_unlock_bh(&sk->sk_callback_lock);
}

+static inline void sock_copy(struct sock *nsk, const struct sock *osk)
+{
+       void *sptr = nsk->sk_security;
+
+       memcpy(nsk, osk, osk->sk_prot->obj_size);
+       nsk->sk_security = sptr;
+       security_sk_clone(osk, nsk);
+}
+
extern int sock_i_uid(struct sock *sk);
extern unsigned long sock_i_ino(struct sock *sk);

--- linux-2.6.17.i686.vanilla/net/core/flow.c   2006-06-17 20:49:35.000000000 
-0500
+++ linux-2.6.17.i686/net/core/flow.c   2006-07-05 14:38:51.000000000 -0500
@@ -32,7 +32,6 @@ struct flow_cache_entry {
        u8                      dir;
        struct flowi            key;
        u32                     genid;
-       u32                     sk_sid;
        void                    *object;
        atomic_t                *object_ref;
};
@@ -165,7 +164,7 @@ static int flow_key_compare(struct flowi
        return 0;
}

-void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir,
+void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
                        flow_resolve_t resolver)
{
        struct flow_cache_entry *fle, **head;
@@ -189,7 +188,6 @@ void *flow_cache_lookup(struct flowi *ke
        for (fle = *head; fle; fle = fle->next) {
                if (fle->family == family &&
                    fle->dir == dir &&
-                   fle->sk_sid == sk_sid &&
                    flow_key_compare(key, &fle->key) == 0) {
                        if (fle->genid == atomic_read(&flow_cache_genid)) {
                                void *ret = fle->object;
@@ -214,7 +212,6 @@ void *flow_cache_lookup(struct flowi *ke
                        *head = fle;
                        fle->family = family;
                        fle->dir = dir;
-                       fle->sk_sid = sk_sid;
                        memcpy(&fle->key, key, sizeof(*key));
                        fle->object = NULL;
                        flow_count(cpu)++;
@@ -226,7 +223,7 @@ nocache:
                void *obj;
                atomic_t *obj_ref;

-               resolver(key, sk_sid, family, dir, &obj, &obj_ref);
+               resolver(key, family, dir, &obj, &obj_ref);

                if (fle) {
                        fle->genid = atomic_read(&flow_cache_genid);
--- linux-2.6.17.i686.vanilla/net/core/sock.c   2006-07-05 14:36:37.000000000 
-0500
+++ linux-2.6.17.i686/net/core/sock.c   2006-07-05 14:38:51.000000000 -0500
@@ -820,7 +820,7 @@ struct sock *sk_clone(struct sock *sk, c
        if (newsk != NULL) {
                struct sk_filter *filter;

-               memcpy(newsk, sk, sk->sk_prot->obj_size);
+               sock_copy(newsk, sk);

                /* SANITY */
                sk_node_init(&newsk->sk_node);
--- linux-2.6.17.i686.vanilla/net/key/af_key.c  2006-06-17 20:49:35.000000000 
-0500
+++ linux-2.6.17.i686/net/key/af_key.c  2006-07-05 14:38:51.000000000 -0500
@@ -2704,6 +2704,9 @@ static int pfkey_send_acquire(struct xfr
#endif
        int sockaddr_size;
        int size;
+       struct sadb_x_sec_ctx *sec_ctx;
+       struct xfrm_sec_ctx *xfrm_ctx;
+       int ctx_size = 0;
        
        sockaddr_size = pfkey_sockaddr_size(x->props.family);
        if (!sockaddr_size)
@@ -2719,6 +2722,11 @@ static int pfkey_send_acquire(struct xfr
        else if (x->id.proto == IPPROTO_ESP)
                size += count_esp_combs(t);

+       if ((xfrm_ctx = x->security)) {
+               ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
+               size +=  sizeof(struct sadb_x_sec_ctx) + ctx_size;
+       }
+
        skb =  alloc_skb(size + 16, GFP_ATOMIC);
        if (skb == NULL)
                return -ENOMEM;
@@ -2814,6 +2822,20 @@ static int pfkey_send_acquire(struct xfr
        else if (x->id.proto == IPPROTO_ESP)
                dump_esp_combs(skb, t);

+       /* security context */
+       if (xfrm_ctx) {
+               sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
+                               sizeof(struct sadb_x_sec_ctx) + ctx_size);
+               sec_ctx->sadb_x_sec_len =
+                 (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
+               sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+               sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+               sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+               sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+               memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+                      xfrm_ctx->ctx_len);
+       }
+
        return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL);
}

--- linux-2.6.17.i686.vanilla/net/xfrm/xfrm_policy.c    2006-06-17 
20:49:35.000000000 -0500
+++ linux-2.6.17.i686/net/xfrm/xfrm_policy.c    2006-07-05 14:38:51.000000000 
-0500
@@ -520,7 +520,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);

/* Find policy to apply to this flow. */

-static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 
dir,
+static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
                               void **objp, atomic_t **obj_refp)
{
        struct xfrm_policy *pol;
@@ -536,7 +536,7 @@ static void xfrm_policy_lookup(struct fl
                match = xfrm_selector_match(sel, fl, family);

                if (match) {
-                       if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) {
+                       if (!security_xfrm_policy_lookup(pol, fl->sid, dir)) {
                                xfrm_pol_hold(pol);
                                break;
                        }
@@ -564,7 +564,7 @@ static inline int policy_to_flow_dir(int
        };
}

-static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, 
struct flowi *fl, u32 sk_sid)
+static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, 
struct flowi *fl)
{
        struct xfrm_policy *pol;

@@ -575,7 +575,7 @@ static struct xfrm_policy *xfrm_sk_polic
                int err = 0;

                if (match)
-                 err = security_xfrm_policy_lookup(pol, sk_sid, 
policy_to_flow_dir(dir));
+                 err = security_xfrm_policy_lookup(pol, fl->sid, 
policy_to_flow_dir(dir));

                if (match && !err)
                        xfrm_pol_hold(pol);
@@ -785,19 +785,20 @@ int xfrm_lookup(struct dst_entry **dst_p
        u32 genid;
        u16 family;
        u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
-       u32 sk_sid = security_sk_sid(sk, fl, dir);
+
+       fl->sid = security_sk_sid(sk, fl, dir);
restart:
        genid = atomic_read(&flow_cache_genid);
        policy = NULL;
        if (sk && sk->sk_policy[1])
-               policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid);
+               policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);

        if (!policy) {
                /* To accelerate a bit...  */
                if ((dst_orig->flags & DST_NOXFRM) || 
!xfrm_policy_list[XFRM_POLICY_OUT])
                        return 0;

-               policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family,
+               policy = flow_cache_lookup(fl, dst_orig->ops->family,
                                           dir, xfrm_policy_lookup);
        }

@@ -955,13 +956,15 @@ int
xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short 
family)
{
        struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+       int err;

        if (unlikely(afinfo == NULL))
                return -EAFNOSUPPORT;

        afinfo->decode_session(skb, fl);
+       err = security_xfrm_decode_session(skb, fl);
        xfrm_policy_put_afinfo(afinfo);
-       return 0;
+       return err;
}
EXPORT_SYMBOL(xfrm_decode_session);

@@ -981,14 +984,11 @@ int __xfrm_policy_check(struct sock *sk,
        struct xfrm_policy *pol;
        struct flowi fl;
        u8 fl_dir = policy_to_flow_dir(dir);
-       u32 sk_sid;

        if (xfrm_decode_session(skb, &fl, family) < 0)
                return 0;
        nf_nat_decode_session(skb, &fl, family);

-       sk_sid = security_sk_sid(sk, &fl, fl_dir);
-
        /* First, check used SA against their selectors. */
        if (skb->sp) {
                int i;
@@ -1002,10 +1002,10 @@ int __xfrm_policy_check(struct sock *sk,

        pol = NULL;
        if (sk && sk->sk_policy[dir])
-               pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid);
+               pol = xfrm_sk_policy_lookup(sk, dir, &fl);

        if (!pol)
-               pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir,
+               pol = flow_cache_lookup(&fl, family, fl_dir,
                                        xfrm_policy_lookup);

        if (!pol)
@@ -1200,6 +1200,8 @@ int xfrm_bundle_ok(struct xfrm_dst *firs

                if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
                        return 0;
+               if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm))
+                       return 0;
                if (dst->xfrm->km.state != XFRM_STATE_VALID)
                        return 0;

--- linux-2.6.17.i686.vanilla/net/xfrm/xfrm_state.c     2006-06-17 
20:49:35.000000000 -0500
+++ linux-2.6.17.i686/net/xfrm/xfrm_state.c     2006-07-05 14:38:51.000000000 
-0500
@@ -366,7 +366,7 @@ xfrm_state_find(xfrm_address_t *daddr, x
                         */
                        if (x->km.state == XFRM_STATE_VALID) {
                                if (!xfrm_selector_match(&x->sel, fl, family) ||
-                                   !xfrm_sec_ctx_match(pol->security, 
x->security))
+                                   !security_xfrm_state_pol_flow_match(x, pol, 
fl))
                                        continue;
                                if (!best ||
                                    best->km.dying > x->km.dying ||
@@ -378,7 +378,7 @@ xfrm_state_find(xfrm_address_t *daddr, x
                        } else if (x->km.state == XFRM_STATE_ERROR ||
                                   x->km.state == XFRM_STATE_EXPIRED) {
                                if (xfrm_selector_match(&x->sel, fl, family) &&
-                                   xfrm_sec_ctx_match(pol->security, 
x->security))
+                                   security_xfrm_state_pol_flow_match(x, pol, 
fl))
                                        error = -ESRCH;
                        }
                }
@@ -402,6 +402,14 @@ xfrm_state_find(xfrm_address_t *daddr, x
                 * to current session. */
                xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);

+               error = security_xfrm_state_alloc_acquire(x, pol->security, 
fl->sid);
+               if (error) {
+                       x->km.state = XFRM_STATE_DEAD;
+                       xfrm_state_put(x);
+                       x = NULL;
+                       goto out;
+               }
+
                if (km_query(x, tmpl, pol) == 0) {
                        x->km.state = XFRM_STATE_ACQ;
                        list_add_tail(&x->bydst, xfrm_state_bydst+h);
--- linux-2.6.17.i686.vanilla/net/xfrm/xfrm_user.c      2006-07-05 
14:36:43.000000000 -0500
+++ linux-2.6.17.i686/net/xfrm/xfrm_user.c      2006-07-05 14:38:51.000000000 
-0500
@@ -907,27 +907,40 @@ rtattr_failure:
        return -1;
}

-static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb)
+static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb)
{
-       if (xp->security) {
-               int ctx_size = sizeof(struct xfrm_sec_ctx) +
-                               xp->security->ctx_len;
-               struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
-               struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
-
-               uctx->exttype = XFRMA_SEC_CTX;
-               uctx->len = ctx_size;
-               uctx->ctx_doi = xp->security->ctx_doi;
-               uctx->ctx_alg = xp->security->ctx_alg;
-               uctx->ctx_len = xp->security->ctx_len;
-               memcpy(uctx + 1, xp->security->ctx_str, xp->security->ctx_len);
-       }
-       return 0;
+       int ctx_size = sizeof(struct xfrm_sec_ctx) + s->ctx_len;
+       struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size);
+       struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+       uctx->exttype = XFRMA_SEC_CTX;
+       uctx->len = ctx_size;
+       uctx->ctx_doi = s->ctx_doi;
+       uctx->ctx_alg = s->ctx_alg;
+       uctx->ctx_len = s->ctx_len;
+       memcpy(uctx + 1, s->ctx_str, s->ctx_len);
+       return 0;

 rtattr_failure:
        return -1;
}

+static inline int copy_to_user_state_sec_ctx(struct xfrm_state *x, struct 
sk_buff *skb)
+{
+       if (x->security) {
+               return copy_sec_ctx(x->security, skb);
+       }
+       return 0;
+}
+
+static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff 
*skb)
+{
+       if (xp->security) {
+               return copy_sec_ctx(xp->security, skb);
+       }
+       return 0;
+}
+
static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void 
*ptr)
{
        struct xfrm_dump_info *sp = ptr;
@@ -1703,7 +1716,7 @@ static int build_acquire(struct sk_buff
        if (copy_to_user_tmpl(xp, skb) < 0)
                goto nlmsg_failure;
-       if (copy_to_user_sec_ctx(xp, skb))
+       if (copy_to_user_state_sec_ctx(x, skb))
                goto nlmsg_failure;

        nlh->nlmsg_len = skb->tail - b;
--- linux-2.6.17.i686.vanilla/security/dummy.c  2006-07-05 14:36:43.000000000 
-0500
+++ linux-2.6.17.i686/security/dummy.c  2006-07-05 14:38:51.000000000 -0500
@@ -789,6 +789,10 @@ static inline void dummy_sk_free_securit
{
}

+static inline void dummy_sk_clone_security (const struct sock *sk, struct sock 
*newsk)
+{
+}
+
static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir)
{
        return 0;
@@ -810,7 +814,8 @@ static void dummy_xfrm_policy_free_secur
{
}

-static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct 
xfrm_user_sec_ctx *sec_ctx)
+static int dummy_xfrm_state_alloc_security(struct xfrm_state *x,
+       struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 sid)
{
        return 0;
}
@@ -823,6 +828,23 @@ static int dummy_xfrm_policy_lookup(stru
{
        return 0;
}
+
+static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
+                               struct xfrm_policy *xp, struct flowi *fl)
+{
+       return 1;
+}
+
+static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state 
*xfrm)
+{
+       return 1;
+}
+
+static int dummy_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl)
+{
+       return 0;
+}
+
#endif /* CONFIG_SECURITY_NETWORK_XFRM */
static int dummy_register_security (const char *name, struct 
security_operations *ops)
{
@@ -1018,6 +1040,7 @@ void security_fixup_ops (struct security
        set_to_dummy_if_null(ops, socket_getpeersec_dgram);
        set_to_dummy_if_null(ops, sk_alloc_security);
        set_to_dummy_if_null(ops, sk_free_security);
+       set_to_dummy_if_null(ops, sk_clone_security);
        set_to_dummy_if_null(ops, sk_getsid);
 #endif /* CONFIG_SECURITY_NETWORK */
#ifdef  CONFIG_SECURITY_NETWORK_XFRM
@@ -1027,6 +1050,9 @@ void security_fixup_ops (struct security
        set_to_dummy_if_null(ops, xfrm_state_alloc_security);
        set_to_dummy_if_null(ops, xfrm_state_free_security);
        set_to_dummy_if_null(ops, xfrm_policy_lookup);
+       set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
+       set_to_dummy_if_null(ops, xfrm_flow_state_match);
+       set_to_dummy_if_null(ops, xfrm_decode_session);
#endif  /* CONFIG_SECURITY_NETWORK_XFRM */
#ifdef CONFIG_KEYS
        set_to_dummy_if_null(ops, key_alloc);
--- linux-2.6.17.i686.vanilla/security/selinux/hooks.c  2006-07-05 
14:36:43.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/hooks.c  2006-07-05 14:38:51.000000000 
-0500
@@ -270,15 +270,13 @@ static int sk_alloc_security(struct sock
{
        struct sk_security_struct *ssec;

-       if (family != PF_UNIX)
-               return 0;
-
        ssec = kzalloc(sizeof(*ssec), priority);
        if (!ssec)
                return -ENOMEM;

        ssec->sk = sk;
        ssec->peer_sid = SECINITSID_UNLABELED;
+       ssec->sid = SECINITSID_UNLABELED;
        sk->sk_security = ssec;

        return 0;
@@ -288,9 +286,6 @@ static void sk_free_security(struct sock
{
        struct sk_security_struct *ssec = sk->sk_security;

-       if (sk->sk_family != PF_UNIX)
-               return;
-
        sk->sk_security = NULL;
        kfree(ssec);
}
@@ -2935,6 +2930,7 @@ static int selinux_socket_post_create(st
{
        struct inode_security_struct *isec;
        struct task_security_struct *tsec;
+       struct sk_security_struct *sksec;

        isec = SOCK_INODE(sock)->i_security;

@@ -2943,6 +2939,11 @@ static int selinux_socket_post_create(st
        isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
        isec->initialized = 1;

+       if (sock->sk) {
+               sksec = sock->sk->sk_security;
+               sksec->sid = isec->sid;
+       }
+
        return selinux_netlbl_socket_create(sock, family, isec->sid);
}

@@ -3336,7 +3337,7 @@ static int selinux_socket_sock_rcv_skb(s
        if (err)
                goto out;

-       err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+       err = selinux_xfrm_sock_rcv_skb(sock_sid, skb, &ad);

out:    
        return err;
@@ -3426,6 +3427,15 @@ static void selinux_sk_free_security(str
        sk_free_security(sk);
}

+static void selinux_sk_clone_security(const struct sock *sk, struct sock 
*newsk)
+{
+       struct sk_security_struct *ssec = sk->sk_security;
+       struct sk_security_struct *newssec = newsk->sk_security;
+
+       newssec->sid = ssec->sid;
+       newssec->peer_sid = ssec->peer_sid;
+}
+
static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi 
*fl, u8 dir)
{
        struct inode_security_struct *isec;
@@ -3439,6 +3449,10 @@ static unsigned int selinux_sk_getsid_se

        if (isec)
                sock_sid = isec->sid;
+       else {
+               struct sk_security_struct *sksec = sk->sk_security;
+               sock_sid = sksec->sid;
+       }

        read_unlock_bh(&sk->sk_callback_lock);
        return sock_sid;
@@ -3582,7 +3596,7 @@ static unsigned int selinux_ip_postroute
        if (err != NF_ACCEPT)
                goto out;

-       err = selinux_xfrm_postroute_last(isec->sid, skb);
+       err = selinux_xfrm_postroute_last(isec->sid, skb, &ad);

out:
        return err;
@@ -4399,6 +4413,7 @@ static struct security_operations selinu
        .socket_getpeersec_dgram =      selinux_socket_getpeersec_dgram,
        .sk_alloc_security =            selinux_sk_alloc_security,
        .sk_free_security =             selinux_sk_free_security,
+       .sk_clone_security =            selinux_sk_clone_security,
        .sk_getsid =                    selinux_sk_getsid_security,

#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -4408,6 +4423,9 @@ static struct security_operations selinu
        .xfrm_state_alloc_security =    selinux_xfrm_state_alloc,
        .xfrm_state_free_security =     selinux_xfrm_state_free,
        .xfrm_policy_lookup =           selinux_xfrm_policy_lookup,
+       .xfrm_state_pol_flow_match =    selinux_xfrm_state_pol_flow_match,
+       .xfrm_flow_state_match =        selinux_xfrm_flow_state_match,
+       .xfrm_decode_session =          selinux_xfrm_decode_session,
#endif
};

--- linux-2.6.17.i686.vanilla/security/selinux/include/av_permissions.h 
2006-06-17 20:49:35.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/include/av_permissions.h 2006-07-05 
14:38:51.000000000 -0500
@@ -909,6 +909,7 @@
#define ASSOCIATION__SENDTO                       0x00000001UL
#define ASSOCIATION__RECVFROM                     0x00000002UL
#define ASSOCIATION__SETCONTEXT                   0x00000004UL
+#define ASSOCIATION__POLMATCH                     0x00000008UL

#define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL      0x00000001UL
#define NETLINK_KOBJECT_UEVENT_SOCKET__READ       0x00000002UL
--- linux-2.6.17.i686.vanilla/security/selinux/include/av_perm_to_string.h      
2006-06-17 20:49:35.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/include/av_perm_to_string.h      
2006-07-05 14:39:17.000000000 -0500
@@ -239,3 +239,4 @@
   S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
   S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
   S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
+   S_(SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, "polmatch")
--- linux-2.6.17.i686.vanilla/security/selinux/include/objsec.h 2006-07-05 
14:36:43.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/include/objsec.h 2006-07-05 
14:38:51.000000000 -0500
@@ -107,6 +107,7 @@ struct netif_security_struct {

struct sk_security_struct {
        struct sock *sk;                /* back pointer to sk object */
+       u32 sid;                        /* SID of this object */
        u32 peer_sid;                   /* SID of peer */
};

--- linux-2.6.17.i686.vanilla/security/selinux/include/security.h       
2006-06-17 20:49:35.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/include/security.h       2006-07-05 
14:38:51.000000000 -0500
@@ -78,6 +78,8 @@ int security_node_sid(u16 domain, void *
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
                                 u16 tclass);

+int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
+
#define SECURITY_FS_USE_XATTR           1 /* use xattr */
#define SECURITY_FS_USE_TRANS           2 /* use transition SIDs, e.g. 
devpts/tmpfs */
#define SECURITY_FS_USE_TASK            3 /* use task SIDs, e.g. pipefs/sockfs 
*/
--- linux-2.6.17.i686.vanilla/security/selinux/include/xfrm.h   2006-06-17 
20:49:35.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/include/xfrm.h   2006-07-05 
14:38:51.000000000 -0500
@@ -2,6 +2,7 @@
 * SELinux support for the XFRM LSM hooks
 *
 * Author : Trent Jaeger, <[EMAIL PROTECTED]>
+ * Updated : Venkat Yekkirala, <[EMAIL PROTECTED]>
 */
#ifndef _SELINUX_XFRM_H_
#define _SELINUX_XFRM_H_
@@ -9,9 +10,14 @@
int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, 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_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx 
*sec_ctx);
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx 
*sec_ctx,
+                       struct xfrm_sec_ctx *pol, u32 sid);
void selinux_xfrm_state_free(struct xfrm_state *x);
-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
+int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_sid, u8 dir);
+int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy 
*xp,
+                       struct flowi *fl);
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm);
+int selinux_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl);

/*
 * Extract the security blob from the sock (it's actually on the socket)
@@ -37,17 +43,21 @@ static inline u32 selinux_no_sk_sid(stru
}

#ifdef CONFIG_SECURITY_NETWORK_XFRM
-int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb);
-int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb);
+int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
+                       struct avc_audit_data *ad);
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
+                       struct avc_audit_data *ad);
u32 selinux_socket_getpeer_stream(struct sock *sk);
u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
#else
-static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
+static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
+                       struct avc_audit_data *ad)
{
        return 0;
}

-static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff 
*skb)
+static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff 
*skb,
+                       struct avc_audit_data *ad)
{
        return NF_ACCEPT;
}
--- linux-2.6.17.i686.vanilla/security/selinux/ss/mls.c 2006-07-05 
14:36:43.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/ss/mls.c 2006-07-05 14:38:51.000000000 
-0500
@@ -219,26 +219,6 @@ int mls_context_isvalid(struct policydb }

/*
- * Copies the MLS range from `src' into `dst'.
- */
-static inline int mls_copy_context(struct context *dst,
-                                  struct context *src)
-{
-       int l, rc = 0;
-
-       /* Copy the MLS range from the source context */
-       for (l = 0; l < 2; l++) {
-               dst->range.level[l].sens = src->range.level[l].sens;
-               rc = ebitmap_cpy(&dst->range.level[l].cat,
-                                &src->range.level[l].cat);
-               if (rc)
-                       break;
-       }
-
-       return rc;
-}
-
-/*
 * Set the MLS fields in the security context structure
 * `context' based on the string representation in
 * the string `*scontext'.  Update `*scontext' to
--- linux-2.6.17.i686.vanilla/security/selinux/ss/mls.h 2006-07-05 
14:36:43.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/ss/mls.h 2006-07-05 14:38:51.000000000 
-0500
@@ -24,6 +24,26 @@
#include "context.h"
#include "policydb.h"

+/*
+ * Copies the MLS range from `src' into `dst'.
+ */
+static inline int mls_copy_context(struct context *dst,
+                                  struct context *src)
+{
+       int l, rc = 0;
+
+       /* Copy the MLS range from the source context */
+       for (l = 0; l < 2; l++) {
+               dst->range.level[l].sens = src->range.level[l].sens;
+               rc = ebitmap_cpy(&dst->range.level[l].cat,
+                                &src->range.level[l].cat);
+               if (rc)
+                       break;
+       }
+
+       return rc;
+}
+
int mls_compute_context_len(struct context *context);
void mls_sid_to_context(struct context *context, char **scontext);
int mls_context_isvalid(struct policydb *p, struct context *c);
--- linux-2.6.17.i686.vanilla/security/selinux/ss/services.c    2006-07-05 
14:36:43.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/ss/services.c    2006-07-05 
14:38:51.000000000 -0500
@@ -1827,6 +1827,54 @@ out:
        return rc;
}

+/*
+ * security_sid_mls_copy() - computes a new sid based on the given
+ * sid and the mls portion of mls_sid.
+ */
+int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
+{
+       struct context *context1 = NULL;
+       struct context *context2 = NULL;
+       struct context newcon;
+       int rc = 0;
+
+       if (!ss_initialized) {
+               *new_sid = sid;
+               goto out;
+       }
+
+       POLICY_RDLOCK;
+       context1 = sidtab_search(&sidtab, sid);
+       if (!context1) {
+               printk(KERN_ERR "security_sid_mls_copy:  unrecognized SID "
+                      "%d\n", sid);
+               rc = -EINVAL;
+               goto out_unlock;
+       }
+
+       context2 = sidtab_search(&sidtab, mls_sid);
+       if (!context2) {
+               printk(KERN_ERR "security_sid_mls_copy:  unrecognized SID "
+                      "%d\n", mls_sid);
+               rc = -EINVAL;
+               goto out_unlock;
+       }
+
+       newcon.user = context1->user;
+       newcon.role = context1->role;
+       newcon.type = context1->type;
+       rc = mls_copy_context(&newcon, context2);
+       if (rc)
+               goto out_unlock;
+
+       rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
+
+out_unlock:
+       POLICY_RDUNLOCK;
+out:
+       return rc;
+}
+
struct selinux_audit_rule {
        u32 au_seqno;
        struct context au_ctxt;
--- linux-2.6.17.i686.vanilla/security/selinux/xfrm.c   2006-06-17 
20:49:35.000000000 -0500
+++ linux-2.6.17.i686/security/selinux/xfrm.c   2006-07-05 14:38:51.000000000 
-0500
@@ -6,7 +6,12 @@
 *  Authors:  Serge Hallyn <[EMAIL PROTECTED]>
 *            Trent Jaeger <[EMAIL PROTECTED]>
 *
+ *  Updated: Venkat Yekkirala <[EMAIL PROTECTED]>
+ *
+ *           Granular IPSec Associations for use in MLS environments.
+ *
 *  Copyright (C) 2005 International Business Machines Corporation
+ *  Copyright (C) 2006 Trusted Computer Solutions, Inc.
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License version 2,
@@ -68,10 +73,10 @@ static inline int selinux_authorizable_x
}

/*
- * LSM hook implementation that authorizes that a socket can be used
- * with the corresponding xfrm_sec_ctx and direction.
+ * LSM hook implementation that authorizes that a flow can use
+ * a xfrm policy rule.
 */
-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
+int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_sid, u8 dir)
{
        int rc = 0;
        u32 sel_sid = SECINITSID_UNLABELED;
@@ -85,27 +90,129 @@ int selinux_xfrm_policy_lookup(struct xf
                sel_sid = ctx->ctx_sid;
        }

-       rc = avc_has_perm(sk_sid, sel_sid, SECCLASS_ASSOCIATION,
-                         ((dir == FLOW_DIR_IN) ? ASSOCIATION__RECVFROM :
-                          ((dir == FLOW_DIR_OUT) ?  ASSOCIATION__SENDTO :
-                           (ASSOCIATION__SENDTO | ASSOCIATION__RECVFROM))),
+       rc = avc_has_perm(fl_sid, sel_sid, SECCLASS_ASSOCIATION,
+                         ASSOCIATION__POLMATCH,
+                         NULL);
+
+       return 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,
+                       struct flowi *fl)
+{
+       u32 state_sid;
+       u32 pol_sid;
+       int err;
+
+       if (x->security)
+               state_sid = x->security->ctx_sid;
+       else
+               state_sid = SECINITSID_UNLABELED;
+
+       if (xp->security)
+               pol_sid = xp->security->ctx_sid;
+       else
+               pol_sid = SECINITSID_UNLABELED;
+
+       err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
+                         ASSOCIATION__POLMATCH,
                          NULL);

+       if (err)
+               return 0;
+
+       return selinux_xfrm_flow_state_match(fl, x);
+}
+
+/*
+ * LSM hook implementation that authorizes that a particular outgoing flow
+ * can use a given security association.
+ */
+
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+{
+       int rc = 0;
+       u32 sel_sid = SECINITSID_UNLABELED;
+       struct xfrm_sec_ctx *ctx;
+
+       /* Context sid is either set to label or ANY_ASSOC */
+       if ((ctx = xfrm->security)) {
+               if (!selinux_authorizable_ctx(ctx))
+                       return 0;
+
+               sel_sid = ctx->ctx_sid;
+       }
+
+       rc = avc_has_perm(fl->sid, sel_sid, SECCLASS_ASSOCIATION,
+                         ASSOCIATION__SENDTO,
+                         NULL)? 0:1;
+
        return rc;
}

/*
+ * LSM hook implementation that determines the sid for the session.
+ */
+
+int selinux_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl)
+{
+       struct sec_path *sp;
+
+       fl->sid = SECSID_NULL;
+
+       if (skb == NULL)
+               return 0;
+
+       sp = skb->sp;
+       if (sp) {
+               int i, sid_set = 0;
+
+               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) {
+                                       fl->sid = ctx->ctx_sid;
+                                       sid_set = 1;
+                               }
+                               else if (fl->sid != ctx->ctx_sid)
+                                       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)
+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)
{
        int rc = 0;
        struct task_security_struct *tsec = current->security;
-       struct xfrm_sec_ctx *ctx;
+       struct xfrm_sec_ctx *ctx = NULL;
+       char *ctx_str = NULL;
+       u32 str_len;
+       u32 ctx_sid;
+
+       BUG_ON(uctx && pol);
+
+       if (pol)
+               goto from_policy;

        BUG_ON(!uctx);
-       BUG_ON(uctx->ctx_doi != XFRM_SC_ALG_SELINUX);
+
+       if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX)
+               return -EINVAL;

        if (uctx->ctx_len >= PAGE_SIZE)
                return -ENOMEM;
@@ -145,9 +252,40 @@ static int selinux_xfrm_sec_ctx_alloc(st

        return rc;

+from_policy:
+       BUG_ON(!pol);
+       rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid);
+       if (rc)
+               goto out;
+
+       rc = security_sid_to_context(ctx_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 = ctx_sid;
+       ctx->ctx_len = str_len;
+       memcpy(ctx->ctx_str,
+              ctx_str,
+              str_len);
+
+       return rc;
+
out:
        *ctxp = NULL;
        kfree(ctx);
+       kfree(ctx_str);
        return rc;
}

@@ -161,7 +299,7 @@ int selinux_xfrm_policy_alloc(struct xfr

        BUG_ON(!xp);

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

@@ -204,13 +342,14 @@ void selinux_xfrm_policy_free(struct xfr
 * LSM hook implementation that allocs and transfers sec_ctx spec to
 * xfrm_state.
 */
-int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx 
*uctx)
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx 
*uctx,
+               struct xfrm_sec_ctx *pol, u32 sid)
{
        int err;

        BUG_ON(!x);

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

@@ -299,38 +438,30 @@ u32 selinux_socket_getpeer_dgram(struct * 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)
+int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
+                               struct avc_audit_data *ad)
{
        int i, rc = 0;
        struct sec_path *sp;
+       u32 sel_sid = SECINITSID_UNLABELED;

        sp = skb->sp;

        if (sp) {
-               /*
-                * __xfrm_policy_check does not approve unless xfrm_policy_ok
-                * says that spi's match for policy and the socket.
-                *
-                *  Only need to verify the existence of an authorizable sp.
-                */
                for (i = 0; i < sp->len; i++) {
                        struct xfrm_state *x = sp->xvec[i];

-                       if (x && selinux_authorizable_xfrm(x))
-                               goto accept;
+                       if (x && selinux_authorizable_xfrm(x)) {
+                               struct xfrm_sec_ctx *ctx = x->security;
+                               sel_sid = ctx->ctx_sid;
+                               break;
+                       }
                }
        }

-       /* check SELinux sock for unlabelled access */
-       rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
-                         ASSOCIATION__RECVFROM, NULL);
-       if (rc)
-               goto drop;
+       rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
+                         ASSOCIATION__RECVFROM, ad);

-accept:
-       return 0;
-
-drop:
        return rc;
}

@@ -341,7 +472,8 @@ drop:
 * If we do have a authorizable security association, then it has already been
 * checked in xfrm_policy_lookup hook.
 */
-int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
+                                       struct avc_audit_data *ad)
{
        struct dst_entry *dst;
        int rc = 0;
@@ -361,7 +493,7 @@ int selinux_xfrm_postroute_last(u32 isec
        }

        rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
-                         ASSOCIATION__SENDTO, NULL);
+                         ASSOCIATION__SENDTO, ad);
        if (rc)
                goto drop;


--
redhat-lspp mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/redhat-lspp

Reply via email to