selinux: look for IPsec labels on both inbound and outbound packets
authorPaul Moore <pmoore@redhat.com>
Tue, 10 Dec 2013 19:57:54 +0000 (14:57 -0500)
committerPaul Moore <pmoore@redhat.com>
Thu, 12 Dec 2013 22:21:31 +0000 (17:21 -0500)
Previously selinux_skb_peerlbl_sid() would only check for labeled
IPsec security labels on inbound packets, this patch enables it to
check both inbound and outbound traffic for labeled IPsec security
labels.

Reported-by: Janak Desai <Janak.Desai@gtri.gatech.edu>
Cc: stable@vger.kernel.org
Signed-off-by: Paul Moore <pmoore@redhat.com>
security/selinux/hooks.c
security/selinux/include/xfrm.h
security/selinux/xfrm.c

index cc076a9..8b28123 100644 (file)
@@ -3829,7 +3829,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
        u32 nlbl_sid;
        u32 nlbl_type;
 
-       err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
+       err = selinux_xfrm_skb_sid(skb, &xfrm_sid);
        if (unlikely(err))
                return -EACCES;
        err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
index 0dec76c..48c3cc9 100644 (file)
@@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb,
 int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
                                struct common_audit_data *ad, u8 proto);
 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid);
 
 static inline void selinux_xfrm_notify_policyload(void)
 {
@@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid,
 static inline void selinux_xfrm_notify_policyload(void)
 {
 }
-#endif
 
-static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
 {
-       return selinux_xfrm_decode_session(skb, sid, 0);
+       *sid = SECSID_NULL;
+       return 0;
 }
+#endif
 
 #endif /* _SELINUX_XFRM_H_ */
index cf79a45..0462cb3 100644 (file)
@@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
                            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)
+static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)
 {
-       u32 sid_session = SECSID_NULL;
-       struct sec_path *sp;
+       struct dst_entry *dst = skb_dst(skb);
+       struct xfrm_state *x;
 
-       if (skb == NULL)
-               goto out;
+       if (dst == NULL)
+               return SECSID_NULL;
+       x = dst->xfrm;
+       if (x == NULL || !selinux_authorizable_xfrm(x))
+               return SECSID_NULL;
+
+       return x->security->ctx_sid;
+}
+
+static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb,
+                                       u32 *sid, int ckall)
+{
+       u32 sid_session = SECSID_NULL;
+       struct sec_path *sp = skb->sp;
 
-       sp = skb->sp;
        if (sp) {
                int i;
 
@@ -247,6 +254,30 @@ out:
        return 0;
 }
 
+/*
+ * 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)
+{
+       if (skb == NULL) {
+               *sid = SECSID_NULL;
+               return 0;
+       }
+       return selinux_xfrm_skb_sid_ingress(skb, sid, ckall);
+}
+
+int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid)
+{
+       int rc;
+
+       rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0);
+       if (rc == 0 && *sid == SECSID_NULL)
+               *sid = selinux_xfrm_skb_sid_egress(skb);
+
+       return rc;
+}
+
 /*
  * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy.
  */