From 0af901643fe3f1f8d44e41115d36609ee4bda2bf Mon Sep 17 00:00:00 2001
From: "Geyslan G. Bem" <geyslan@gmail.com>
Date: Wed, 4 Dec 2013 16:10:24 -0500
Subject: selinux: fix possible memory leak

Free 'ctx_str' when necessary.

Signed-off-by: Geyslan G. Bem <geyslan@gmail.com>
Signed-off-by: Paul Moore <pmoore@redhat.com>
---
 security/selinux/xfrm.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

(limited to 'security/selinux/xfrm.c')

diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index a91d205ec0c..cf79a4564e3 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -327,19 +327,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
 		return rc;
 
 	ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
-	if (!ctx)
-		return -ENOMEM;
+	if (!ctx) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	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;
+out:
+	kfree(ctx_str);
+	return rc;
 }
 
 /*
-- 
cgit v1.2.3-70-g09d2


From 817eff718dca4e54d5721211ddde0914428fbb7c Mon Sep 17 00:00:00 2001
From: Paul Moore <pmoore@redhat.com>
Date: Tue, 10 Dec 2013 14:57:54 -0500
Subject: selinux: look for IPsec labels on both inbound and outbound packets

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        |  2 +-
 security/selinux/include/xfrm.h |  8 ++++---
 security/selinux/xfrm.c         | 51 +++++++++++++++++++++++++++++++++--------
 3 files changed, 47 insertions(+), 14 deletions(-)

(limited to 'security/selinux/xfrm.c')

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index cc076a9b034..8b2812312ae 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -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);
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 0dec76c64cf..48c3cc94c16 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -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_ */
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index cf79a4564e3..0462cb3ff0a 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -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.
  */
-- 
cgit v1.2.3-70-g09d2