netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!)
@ 2006-10-09 19:42 paul.moore
  2006-10-09 19:42 ` [PATCH 01/11] secid reconciliation: new SELinux flask definitions paul.moore
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

This patchset represents all of the secid reconciliation work done thus far by
Venkat Yekkirala and myself; you will notice from the 'From:' lines that all of
the patches with the exception of one are his so please make sure you include
him in any replies.

While this patchset is new the patches it contains have been under discussion
for several weeks now, and for those of you following the discussions here and
on the SELinux mailing lists you should not see any surprises here.  The
patchset includes the original nine patches from Venkat (I rolled his small
NETMSG update patch into these original nine as it made the most sense), the
fixup patch Venkat posted this morning, and my patch to add the missing
NetLabel support.  Those who look closely may notice that I have made slight
changes to Venkat's patches; these changes were made so the patch applied
cleanly to the latest net-2.6 git tree and compiled without warnings.  Venkat
and I have discussed these changes and he approves of them.

Please consider this for inclusion into 2.6.20.  If it's too soon to be
thinking of 2.6.20 let me know and I'll rebase/resend this patchset once I see
notice of David's net-2.6.20 git tree.

Thanks.

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/11] secid reconciliation: new SELinux flask definitions
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 02/11] secid reconciliation: Add LSM hooks paul.moore
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-1 --]
[-- Type: text/plain, Size: 3673 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

This patchset helps with leveraging secmark in defining fine-grained security
check points with support for a. a default place holder domain defined using
secmark for each of the check points and b. flow control and reconciliation
of domains entering/leaving the system.

The reconciliation steps for SELinux are explained in the Labeled Networking
document at:
http://marc.theaimsgroup.com/?l=linux-netdev&m=115136637800361&w=2

Also please refer to the discussion at:
http://marc.theaimsgroup.com/?l=selinux&m=115885031311565&w=2

The following are the identifiers handled here:

1. secmark on the skb
2. xfrm security identifier associated with the skb if it used any xfrms,
 a zero secid otherwise.

The following features are included:

- Retain secmark (from the originating socket/flow) on loopback traffic;
  this traffic is now flow controlled on the outbound only.

- When multiple iptables labeling rules are present (e.g.: both on PREROUTING and INPUT)
	INBOUND: The label in the last rule will prevail.
	OUTBOUND: secmark (from the originating socket) is flow-controlled against
		the label on the first rule, and, if it passes, the label on the
		first rule overrides the secmark (from the originating socket).
		This secmark is flow controlled against labels on the subsequent
		rules, each time, overridden by those labels.

- Forwarded packets: The FORWARD chain is treated as an outbound chain for flow
  control purposes. e.g: label with PREROUTING and flow-control with FORWARD or
  POSTROUTING.

- SELinux postroute_last hook: unfortunately, the secmark Vs. UNLABELED SID check
  will be done for ALL traffic (couldn't figure out a way to except traffic already
  processed by (CONN)SECMARK outbound rules).


This patch: Add new flask definitions to SELinux

Adds a new avperm "flow_in" to arbitrate among the identifiers on the
inbound (input/forward). Also adds a new avperm "flow_out" to enable flow
control checks on the outbound (output/forward), addressed in this patch
as well.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 security/selinux/include/av_perm_to_string.h |    2 ++
 security/selinux/include/av_permissions.h    |    2 ++
 2 files changed, 4 insertions(+)

diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 09fc8a2..1e65d28 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -245,6 +245,8 @@
    S_(SECCLASS_PACKET, PACKET__SEND, "send")
    S_(SECCLASS_PACKET, PACKET__RECV, "recv")
    S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
+   S_(SECCLASS_PACKET, PACKET__FLOW_IN, "flow_in")
+   S_(SECCLASS_PACKET, PACKET__FLOW_OUT, "flow_out")
    S_(SECCLASS_KEY, KEY__VIEW, "view")
    S_(SECCLASS_KEY, KEY__READ, "read")
    S_(SECCLASS_KEY, KEY__WRITE, "write")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 81f4f52..2faf3d8 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -962,6 +962,8 @@ #define APPLETALK_SOCKET__NAME_BIND     
 #define PACKET__SEND                              0x00000001UL
 #define PACKET__RECV                              0x00000002UL
 #define PACKET__RELABELTO                         0x00000004UL
+#define PACKET__FLOW_IN                           0x00000008UL
+#define PACKET__FLOW_OUT                          0x00000010UL
 
 #define KEY__VIEW                                 0x00000001UL
 #define KEY__READ                                 0x00000002UL

--
paul moore
linux security @ hp

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/11] secid reconciliation: Add LSM hooks
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
  2006-10-09 19:42 ` [PATCH 01/11] secid reconciliation: new SELinux flask definitions paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 03/11] secid reconciliation: Invoke LSM hook for inbound traffic paul.moore
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-2 --]
[-- Type: text/plain, Size: 4223 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

Add skb_policy_check and skb_netfilter_check hooks to LSM to enable
reconciliation of the various security identifiers as well as enforce
flow control on inbound (PREROUTING/INPUT) and outbound (OUTPUT/FORWARD/POSTROUTING)
traffic.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 include/linux/security.h |   41 ++++++++++++++++++++++++++++++++++++++++-
 security/dummy.c         |   13 +++++++++++++
 2 files changed, 53 insertions(+), 1 deletion(-)

Index: net-2.6_secidfinal/include/linux/security.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/security.h
+++ net-2.6_secidfinal/include/linux/security.h
@@ -828,6 +828,15 @@ struct request_sock;
  *	Sets the new child socket's sid to the openreq sid.
  * @req_classify_flow:
  *	Sets the flow's sid to the openreq sid.
+ * @skb_flow_in:
+ *	Checks to see if security policy would allow skb into the system
+ *	while also reconciling the xfrm secid, cipso, etc, if any, and
+ *	relabeling the skb with the reconciled secid.
+ *	Returns 1 if skb allowed into system, 0 otherwise.
+ * @skb_flow_out:
+ *	Checks to see if security policy would allow skb to go out of system.
+ *	Returns 1 if skb allowed out of system, 0 if not, and -ENOENT if there's
+ *	no hook defined.
  *
  * Security hooks for XFRM operations.
  *
@@ -1372,6 +1381,8 @@ struct security_operations {
 					struct request_sock *req);
 	void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
 	void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
+	int (*skb_flow_in)(struct sk_buff *skb, unsigned short family);
+	int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid);
 #endif	/* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2947,6 +2958,18 @@ static inline void security_req_classify
 	security_ops->req_classify_flow(req, fl);
 }
 
+static inline int security_skb_flow_in(struct sk_buff *skb,
+					unsigned short family)
+{
+	return security_ops->skb_flow_in(skb, family);
+}
+
+static inline int security_skb_flow_out(struct sk_buff *skb,
+					u32 nf_secid)
+{
+	return security_ops->skb_flow_out(skb, nf_secid);
+}
+
 static inline void security_sock_graft(struct sock* sk, struct socket *parent)
 {
 	security_ops->sock_graft(sk, parent);
@@ -3098,6 +3121,18 @@ static inline void security_req_classify
 {
 }
 
+static inline int security_skb_flow_in(struct sk_buff *skb,
+					unsigned short family)
+{
+	return 1;
+}
+
+static inline int security_skb_flow_out(struct sk_buff *skb,
+					u32 nf_secid)
+{
+	return -ENOENT;
+}
+
 static inline void security_sock_graft(struct sock* sk, struct socket *parent)
 {
 }
@@ -3151,7 +3186,11 @@ static inline int security_xfrm_state_al
 {
 	if (!polsec)
 		return 0;
-	return security_ops->xfrm_state_alloc_security(x, NULL, polsec, secid);
+	/*
+	 * No need to pass polsec along since we want the context to be
+	 * taken from secid which is usually from the sock.
+	 */
+	return security_ops->xfrm_state_alloc_security(x, NULL, NULL, secid);
 }
 
 static inline int security_xfrm_state_delete(struct xfrm_state *x)
Index: net-2.6_secidfinal/security/dummy.c
===================================================================
--- net-2.6_secidfinal.orig/security/dummy.c
+++ net-2.6_secidfinal/security/dummy.c
@@ -832,6 +832,17 @@ static inline void dummy_req_classify_fl
 			struct flowi *fl)
 {
 }
+
+static inline int dummy_skb_flow_in(struct sk_buff *skb,
+			unsigned short family)
+{
+	return -ENOENT;
+}
+
+static inline int dummy_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+{
+	return -ENOENT;
+}
 #endif	/* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1108,6 +1119,8 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, inet_conn_request);
 	set_to_dummy_if_null(ops, inet_csk_clone);
 	set_to_dummy_if_null(ops, req_classify_flow);
+	set_to_dummy_if_null(ops, skb_flow_in);
+	set_to_dummy_if_null(ops, skb_flow_out);
  #endif	/* CONFIG_SECURITY_NETWORK */
 #ifdef  CONFIG_SECURITY_NETWORK_XFRM
 	set_to_dummy_if_null(ops, xfrm_policy_alloc_security);

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 03/11] secid reconciliation: Invoke LSM hook for inbound traffic
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
  2006-10-09 19:42 ` [PATCH 01/11] secid reconciliation: new SELinux flask definitions paul.moore
  2006-10-09 19:42 ` [PATCH 02/11] secid reconciliation: Add LSM hooks paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 04/11] secid reconciliation: Invoke LSM hook for outbound traffic paul.moore
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-3 --]
[-- Type: text/plain, Size: 2712 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

Invoke the skb_flow_in LSM hook for inbound
traffic for secid reconciliation and flow control.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 include/net/xfrm.h |   45 +++++++++++++++++++++----------------------
 1 file changed, 22 insertions(+), 23 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 11e0b1d..8f9c184 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -675,22 +675,18 @@ extern int __xfrm_policy_check(struct so
 
 static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
 {
-	if (sk && sk->sk_policy[XFRM_POLICY_IN])
-		return __xfrm_policy_check(sk, dir, skb, family);
-
-	return	(!xfrm_policy_count[dir] && !skb->sp) ||
-		(skb->dst->flags & DST_NOPOLICY) ||
-		__xfrm_policy_check(sk, dir, skb, family);
-}
-
-static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
-{
-	return xfrm_policy_check(sk, dir, skb, AF_INET);
-}
+	int ret;
 
-static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
-{
-	return xfrm_policy_check(sk, dir, skb, AF_INET6);
+	if (sk && sk->sk_policy[XFRM_POLICY_IN])
+		ret = __xfrm_policy_check(sk, dir, skb, family);
+	else
+		ret = (!xfrm_policy_count[dir] && !skb->sp) ||
+		      (skb->dst->flags & DST_NOPOLICY) ||
+		      __xfrm_policy_check(sk, dir, skb, family);
+
+	if (ret)
+		ret = security_skb_flow_in(skb, family);
+	return ret;
 }
 
 extern int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family);
@@ -742,19 +738,22 @@ static inline void xfrm_sk_free_policy(s
 static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; }
 static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; }  
 static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; } 
-static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
-{ 
-	return 1; 
-} 
+static inline int xfrm_policy_check(struct sock *sk, int dir,
+		struct sk_buff *skb, unsigned short family)
+{
+	return security_skb_flow_in(skb, family);
+}
+#endif
+
 static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
 {
-	return 1;
+	return xfrm_policy_check(sk, dir, skb, AF_INET);
 }
-static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family)
+
+static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
 {
-	return 1;
+	return xfrm_policy_check(sk, dir, skb, AF_INET6);
 }
-#endif
 
 static __inline__
 xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family)

--
paul moore
linux security @ hp

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/11] secid reconciliation: Invoke LSM hook for outbound traffic
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (2 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 03/11] secid reconciliation: Invoke LSM hook for inbound traffic paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 05/11] secid reconciliation: Label locally generated IPv6 traffic paul.moore
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-4 --]
[-- Type: text/plain, Size: 5590 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

Invoke the skb_flow_out LSM hook for outbound
traffic for secid reconciliation and flow control.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 net/netfilter/xt_CONNSECMARK.c |   72 ++++++++++++++++++++++++-------
 net/netfilter/xt_SECMARK.c     |   45 ++++++++++++++++++-
 2 files changed, 100 insertions(+), 17 deletions(-)

diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
index 4673862..cca4a0c 100644
--- a/net/netfilter/xt_CONNSECMARK.c
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -17,6 +17,8 @@
  */
 #include <linux/module.h>
 #include <linux/skbuff.h>
+#include <linux/security.h>
+#include <linux/netfilter_ipv6.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_CONNSECMARK.h>
 #include <net/netfilter/nf_conntrack_compat.h>
@@ -29,38 +31,78 @@ MODULE_DESCRIPTION("ip[6]tables CONNSECM
 MODULE_ALIAS("ipt_CONNSECMARK");
 MODULE_ALIAS("ip6t_CONNSECMARK");
 
+static inline int outbound(unsigned short family, unsigned int hooknum)
+{
+	if ((family == AF_INET &&
+		(hooknum == NF_IP_POST_ROUTING ||
+		 hooknum == NF_IP_LOCAL_OUT ||
+		 hooknum == NF_IP_FORWARD)) ||
+	    (family == AF_INET6 &&
+		(hooknum == NF_IP6_POST_ROUTING ||
+		 hooknum == NF_IP6_LOCAL_OUT ||
+		 hooknum == NF_IP6_FORWARD)))
+		return 1;
+	else
+		return 0;
+}
+
 /*
  * If the packet has a security mark and the connection does not, copy
  * the security mark from the packet to the connection.
  */
-static void secmark_save(struct sk_buff *skb)
+static void secmark_save(struct sk_buff *skb, unsigned int hooknum)
 {
 	if (skb->secmark) {
 		u32 *connsecmark;
 		enum ip_conntrack_info ctinfo;
 
 		connsecmark = nf_ct_get_secmark(skb, &ctinfo);
-		if (connsecmark && !*connsecmark)
+		if (connsecmark)
 			if (*connsecmark != skb->secmark)
 				*connsecmark = skb->secmark;
 	}
 }
 
 /*
- * If packet has no security mark, and the connection does, restore the
- * security mark from the connection to the packet.
+ * On the inbound, restore the security mark from the connection to the packet.
+ * On the outbound, filter based on the current secmark.
  */
-static void secmark_restore(struct sk_buff *skb)
+static unsigned int secmark_restore(struct sk_buff *skb, unsigned int hooknum,
+		   const struct net_device *in, unsigned short family)
 {
-	if (!skb->secmark) {
-		u32 *connsecmark;
-		enum ip_conntrack_info ctinfo;
-
-		connsecmark = nf_ct_get_secmark(skb, &ctinfo);
-		if (connsecmark && *connsecmark)
-			if (skb->secmark != *connsecmark)
-				skb->secmark = *connsecmark;
+	u32 *psecmark;
+	enum ip_conntrack_info ctinfo;
+
+	psecmark = nf_ct_get_secmark(skb, &ctinfo);
+
+	if (psecmark && *psecmark) {
+
+		/* Set secmark on inbound and filter it on outbound */
+		if (outbound(family, hooknum)) {
+			int err;
+
+			err = security_skb_flow_out(skb, *psecmark);
+			if (!err)
+				return NF_DROP;
+		} else
+			/* 
+			 * inbound:
+			 * loopback traffic should already be labeled
+			 * and any filtering on outbound should suffice
+			 */
+			if (in == &loopback_dev)
+				goto out;
+
+		/*
+		 * inbound or done with outbound check or no LSM hook
+		 * for outbound
+		 */
+		if (skb->secmark != *psecmark)
+			skb->secmark = *psecmark;
 	}
+
+out:
+	return XT_CONTINUE;
 }
 
 static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
@@ -73,11 +115,11 @@ static unsigned int target(struct sk_buf
 
 	switch (info->mode) {
 	case CONNSECMARK_SAVE:
-		secmark_save(skb);
+		secmark_save(skb, hooknum);
 		break;
 
 	case CONNSECMARK_RESTORE:
-		secmark_restore(skb);
+		return secmark_restore(skb, hooknum, in, target->family);
 		break;
 
 	default:
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index add7521..9ecce66 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -15,8 +15,10 @@
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/selinux.h>
+#include <linux/security.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_SECMARK.h>
+#include <linux/netfilter_ipv6.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
@@ -28,6 +30,21 @@ #define PFX "SECMARK: "
 
 static u8 mode;
 
+static inline int outbound(unsigned short family, unsigned int hooknum)
+{
+	if ((family == AF_INET &&
+		(hooknum == NF_IP_POST_ROUTING ||
+		 hooknum == NF_IP_LOCAL_OUT ||
+		 hooknum == NF_IP_FORWARD)) ||
+	    (family == AF_INET6 &&
+		(hooknum == NF_IP6_POST_ROUTING ||
+		 hooknum == NF_IP6_LOCAL_OUT ||
+		 hooknum == NF_IP6_FORWARD)))
+		return 1;
+	else
+		return 0;
+}
+
 static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
 			   const struct net_device *out, unsigned int hooknum,
 			   const struct xt_target *target,
@@ -47,9 +64,33 @@ static unsigned int target(struct sk_buf
 		BUG();
 	}
 
-	if ((*pskb)->secmark != secmark)
-		(*pskb)->secmark = secmark;
+	if (secmark) {
+
+		/* Set secmark on inbound and filter it on outbound */
+		if (outbound(target->family, hooknum)) {
+			int err;
+
+			err = security_skb_flow_out(*pskb, secmark);
+			if (!err)
+				return NF_DROP;
+		} else
+			/*
+			 * inbound:
+			 * loopback traffic should already be labeled
+			 * and any filtering on outbound should suffice
+			 */
+			if (in == &loopback_dev)
+				goto out;
+
+		/* 
+		 * inbound or done with outbound check or no LSM hook
+		 * for outbound
+		 */
+		if ((*pskb)->secmark != secmark)
+			(*pskb)->secmark = secmark;
+	}
 
+out:
 	return XT_CONTINUE;
 }
 

--
paul moore
linux security @ hp

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/11] secid reconciliation: Label locally generated IPv6 traffic
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (3 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 04/11] secid reconciliation: Invoke LSM hook for outbound traffic paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 06/11] secid reconciliation: Label locally generated IPv4 traffic paul.moore
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-5 --]
[-- Type: text/plain, Size: 2725 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

This labels the skb(s) for locally generated IPv6 traffic. This will
be used in pertinent flow control checks on the outbound later in the
LSM hook.

NOTE: Forwarded traffic is already labeled with the reconciled
secmark on the inbound.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 include/linux/skbuff.h           |   29 +++++++++++++++++++++++++++++
 net/ipv6/ip6_output.c            |    5 +++++
 net/ipv6/netfilter/ip6t_REJECT.c |    2 ++
 3 files changed, 36 insertions(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 85577a4..18967f2 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -29,6 +29,7 @@ #include <linux/net.h>
 #include <linux/textsearch.h>
 #include <net/checksum.h>
 #include <linux/dmaengine.h>
+#include <net/flow.h>
 
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
@@ -1499,5 +1500,33 @@ static inline int skb_is_gso(const struc
 	return skb_shinfo(skb)->gso_size;
 }
 
+#ifdef CONFIG_SECURITY_NETWORK
+
+static inline void security_skb_classify_skb(struct sk_buff *from,
+					struct sk_buff *skb)
+{
+	skb->secmark = from->secmark;
+}
+
+static inline void security_flow_classify_skb(struct flowi *fl,
+					struct sk_buff *skb)
+{
+	skb->secmark = fl->secid;
+}
+
+#else
+
+static inline void security_skb_classify_skb(struct sk_buff *from,
+					struct sk_buff *skb)
+{
+}
+
+static inline void security_flow_classify_skb(struct flowi *fl,
+					struct sk_buff *skb)
+{
+}
+
+#endif /* CONFIG_SECURITY_NETWORK */
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 6671691..6648eb3 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -170,6 +170,8 @@ int ip6_xmit(struct sock *sk, struct sk_
 	int hlimit, tclass;
 	u32 mtu;
 
+	security_flow_classify_skb(fl, skb);
+
 	if (opt) {
 		int head_room;
 
@@ -1150,6 +1152,9 @@ alloc_new_skb:
 			}
 			if (skb == NULL)
 				goto error;
+
+			security_flow_classify_skb(fl, skb);
+
 			/*
 			 *	Fill in the control structures
 			 */
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 311eae8..0508c30 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -128,6 +128,8 @@ static void send_reset(struct sk_buff *o
 	ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
 	ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
 
+	security_skb_classify_skb(oldskb, nskb);
+
 	tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
 	/* Truncate to length (no data) */
 	tcph->doff = sizeof(struct tcphdr)/4;

--
paul moore
linux security @ hp

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/11] secid reconciliation: Label locally generated IPv4 traffic
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (4 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 05/11] secid reconciliation: Label locally generated IPv6 traffic paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 07/11] secid reconciliation: Enforcement for SELinux paul.moore
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-6 --]
[-- Type: text/plain, Size: 5980 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

This labels the skb(s) for locally generated IPv4 traffic. This will
be used in pertinent flow control checks on the outbound later in the
LSM hook.

This is not as pretty as it is for IPv6, but what to do?
Note that skb(s) that derive the secmark from the originating socket
do so in the outbound hook.

NOTE: Forwarded traffic is already labeled with the reconciled
secmark on the inbound.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 include/net/ip.h           |   31 +++++++++++++++++++++++++++++++
 include/net/request_sock.h |   18 ++++++++++++++++++
 net/dccp/ipv4.c            |    5 +++++
 net/ipv4/icmp.c            |    4 ++++
 net/ipv4/ip_output.c       |    6 ++++++
 net/ipv4/tcp_ipv4.c        |    1 +
 6 files changed, 65 insertions(+)

Index: net-2.6_secidfinal/include/net/ip.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/ip.h
+++ net-2.6_secidfinal/include/net/ip.h
@@ -48,6 +48,9 @@ struct ipcm_cookie
 	__be32			addr;
 	int			oif;
 	struct ip_options	*opt;
+#ifdef CONFIG_SECURITY_NETWORK
+	u32			secid;
+#endif /* CONFIG_SECURITY_NETWORK */
 };
 
 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
@@ -383,4 +386,32 @@ extern int ip_misc_proc_init(void);
 
 extern struct ctl_table ipv4_table[];
 
+#ifdef CONFIG_SECURITY_NETWORK
+
+static inline void security_skb_classify_ipcm(struct sk_buff *skb,
+					struct ipcm_cookie *ipc)
+{
+	ipc->secid = skb->secmark;
+}
+
+static inline void security_ipcm_classify_skb(struct ipcm_cookie *ipc,
+					struct sk_buff *skb)
+{
+	skb->secmark = ipc->secid;
+}
+
+#else
+
+static inline void security_skb_classify_ipcm(struct sk_buff *skb,
+					struct ipcm_cookie *ipc)
+{
+}
+
+static inline void security_ipcm_classify_skb(struct ipcm_cookie *ipc,
+					struct sk_buff *skb)
+{
+}
+
+#endif /* CONFIG_SECURITY_NETWORK */
+
 #endif	/* _IP_H */
Index: net-2.6_secidfinal/include/net/request_sock.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/request_sock.h
+++ net-2.6_secidfinal/include/net/request_sock.h
@@ -54,6 +54,7 @@ struct request_sock {
 	struct request_sock_ops		*rsk_ops;
 	struct sock			*sk;
 	u32				secid;
+	u32				peer_secid;
 };
 
 static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
@@ -259,4 +260,21 @@ static inline void reqsk_queue_hash_req(
 	write_unlock(&queue->syn_wait_lock);
 }
 
+#ifdef CONFIG_SECURITY_NETWORK
+
+static inline void security_req_classify_skb(struct request_sock *req,
+					struct sk_buff *skb)
+{
+	skb->secmark = req->secid;
+}
+
+#else
+
+static inline void security_req_classify_skb(struct request_sock *req,
+					struct sk_buff *skb)
+{
+}
+
+#endif /* CONFIG_SECURITY_NETWORK */
+
 #endif /* _REQUEST_SOCK_H */
Index: net-2.6_secidfinal/net/dccp/ipv4.c
===================================================================
--- net-2.6_secidfinal.orig/net/dccp/ipv4.c
+++ net-2.6_secidfinal/net/dccp/ipv4.c
@@ -230,6 +230,8 @@ static void dccp_v4_reqsk_send_ack(struc
 	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
 			 DCCP_SKB_CB(rxskb)->dccpd_seq);
 
+	security_req_classify_skb(req, skb);
+
 	bh_lock_sock(dccp_v4_ctl_socket->sk);
 	err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
 				    rxskb->nh.iph->daddr,
@@ -261,6 +263,7 @@ static int dccp_v4_send_response(struct 
 		dh->dccph_checksum = dccp_v4_checksum(skb, ireq->loc_addr,
 						      ireq->rmt_addr);
 		memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+		security_req_classify_skb(req, skb);
 		err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
 					    ireq->rmt_addr,
 					    ireq->opt);
@@ -743,6 +746,8 @@ static void dccp_v4_ctl_send_reset(struc
 	dh->dccph_checksum = dccp_v4_checksum(skb, rxskb->nh.iph->saddr,
 					      rxskb->nh.iph->daddr);
 
+	security_skb_classify_skb(rxskb, skb);
+
 	bh_lock_sock(dccp_v4_ctl_socket->sk);
 	err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
 				    rxskb->nh.iph->daddr,
Index: net-2.6_secidfinal/net/ipv4/icmp.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/icmp.c
+++ net-2.6_secidfinal/net/ipv4/icmp.c
@@ -389,6 +389,8 @@ static void icmp_reply(struct icmp_bxm *
 	if (icmp_xmit_lock())
 		return;
 
+	security_skb_classify_ipcm(skb, &ipc);
+
 	icmp_param->data.icmph.checksum = 0;
 	icmp_out_count(icmp_param->data.icmph.type);
 
@@ -507,6 +509,8 @@ void icmp_send(struct sk_buff *skb_in, i
 	if (icmp_xmit_lock())
 		return;
 
+	security_skb_classify_ipcm(skb_in, &ipc);
+
 	/*
 	 *	Construct source address and options.
 	 */
Index: net-2.6_secidfinal/net/ipv4/ip_output.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/ip_output.c
+++ net-2.6_secidfinal/net/ipv4/ip_output.c
@@ -926,6 +926,8 @@ alloc_new_skb:
 			if (skb == NULL)
 				goto error;
 
+			security_ipcm_classify_skb(ipc, skb);
+
 			/*
 			 *	Fill in the control structures
 			 */
@@ -1122,6 +1124,8 @@ ssize_t	ip_append_page(struct sock *sk, 
 				goto error;
 			}
 
+			security_skb_classify_skb(skb_prev, skb);
+
 			/*
 			 *	Fill in the control structures
 			 */
@@ -1349,6 +1353,8 @@ void ip_send_reply(struct sock *sk, stru
 	daddr = ipc.addr = rt->rt_src;
 	ipc.opt = NULL;
 
+	security_skb_classify_ipcm(skb, &ipc);
+
 	if (replyopts.opt.optlen) {
 		ipc.opt = &replyopts.opt;
 
Index: net-2.6_secidfinal/net/ipv4/tcp_ipv4.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/tcp_ipv4.c
+++ net-2.6_secidfinal/net/ipv4/tcp_ipv4.c
@@ -658,6 +658,7 @@ static int tcp_v4_send_synack(struct soc
 					 ireq->rmt_addr,
 					 csum_partial((char *)th, skb->len,
 						      skb->csum));
+		security_req_classify_skb(req, skb);
 
 		err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
 					    ireq->rmt_addr,

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 07/11] secid reconciliation: Enforcement for SELinux
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (5 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 06/11] secid reconciliation: Label locally generated IPv4 traffic paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 08/11] secid reconciliation: Use secmark when classifying flow using skb paul.moore
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-7 --]
[-- Type: text/plain, Size: 11468 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

This defines SELinux enforcement of the 2 new LSM hooks as well
as related changes elsewhere in the SELinux code.

This also now keeps track of the peersid thru the establishment
of a connection on the server (tracking peersid on the client
is covered later in this patch set).

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 security/selinux/hooks.c        |  151 +++++++++++++++++++++++++++++++---------
 security/selinux/include/xfrm.h |   11 +-
 security/selinux/xfrm.c         |   66 +++++++----------
 3 files changed, 152 insertions(+), 76 deletions(-)

Index: net-2.6_secidfinal/security/selinux/hooks.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/hooks.c
+++ net-2.6_secidfinal/security/selinux/hooks.c
@@ -3461,8 +3461,12 @@ static int selinux_sock_rcv_skb_compat(s
 
 		err = avc_has_perm(sock_sid, port_sid,
 				   sock_class, recv_perm, ad);
+		if (err)
+			goto out;
 	}
 
+	err = selinux_xfrm_sock_rcv_skb(sock_sid, skb, ad);
+
 out:
 	return err;
 }
@@ -3501,10 +3505,6 @@ static int selinux_socket_sock_rcv_skb(s
 		goto out;
 
 	err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad);
-	if (err)
-		goto out;
-
-	err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
 out:	
 	return err;
 }
@@ -3517,7 +3517,7 @@ static int selinux_socket_getpeersec_str
 	u32 scontext_len;
 	struct sk_security_struct *ssec;
 	struct inode_security_struct *isec;
-	u32 peer_sid = 0;
+	u32 peer_sid;
 
 	isec = SOCK_INODE(sock)->i_security;
 
@@ -3528,8 +3528,10 @@ static int selinux_socket_getpeersec_str
 	}
 	else if (isec->sclass == SECCLASS_TCP_SOCKET) {
 		peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
-		if (peer_sid == SECSID_NULL)
-			peer_sid = selinux_socket_getpeer_stream(sock->sk);
+		if (peer_sid == SECSID_NULL) {
+			ssec = sock->sk->sk_security;
+			peer_sid = ssec->peer_sid;
+		}
 		if (peer_sid == SECSID_NULL) {
 			err = -ENOPROTOOPT;
 			goto out;
@@ -3562,7 +3564,8 @@ out:	
 	return err;
 }
 
-static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
+static int selinux_socket_getpeersec_dgram(struct socket *sock,
+				struct sk_buff *skb, u32 *secid)
 {
 	u32 peer_secid = SECSID_NULL;
 	int err = 0;
@@ -3571,8 +3574,12 @@ static int selinux_socket_getpeersec_dgr
 		selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
 	else if (skb) {
 		peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb);
-		if (peer_secid == SECSID_NULL)
-			peer_secid = selinux_socket_getpeer_dgram(skb);
+		if (peer_secid == SECSID_NULL) {
+			if (selinux_compat_net)
+				peer_secid = selinux_socket_getpeer_dgram(skb);
+			else
+				peer_secid = skb->secmark;
+		}
 	}
 
 	if (peer_secid == SECSID_NULL)
@@ -3640,19 +3647,24 @@ static int selinux_inet_conn_request(str
 		return 0;
 	}
 
-	err = selinux_xfrm_decode_session(skb, &peersid, 0);
-	BUG_ON(err);
-
-	if (peersid == SECSID_NULL) {
-		req->secid = sksec->sid;
-		return 0;
-	}
+	if (selinux_compat_net) {
+		err = selinux_xfrm_decode_session(skb, &peersid, 0);
+		BUG_ON(err);
+
+		if (peersid == SECSID_NULL) {
+			req->secid = sksec->sid;
+			req->peer_secid = 0;
+			return 0;
+		}
+	} else
+		peersid = skb->secmark;
 
 	err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
 	if (err)
 		return err;
 
 	req->secid = newsid;
+	req->peer_secid = peersid;
 	return 0;
 }
 
@@ -3662,6 +3674,7 @@ static void selinux_inet_csk_clone(struc
 	struct sk_security_struct *newsksec = newsk->sk_security;
 
 	newsksec->sid = req->secid;
+	newsksec->peer_sid = req->peer_secid;
 	/* NOTE: Ideally, we should also get the isec->sid for the
 	   new socket in sync, but we don't have the isec available yet.
 	   So we will wait until sock_graft to do it, by which
@@ -3676,6 +3689,67 @@ static void selinux_req_classify_flow(co
 	fl->secid = req->secid;
 }
 
+static int selinux_skb_flow_in(struct sk_buff *skb, unsigned short family)
+{
+	u32 xfrm_sid;
+	int err;
+
+	if (selinux_compat_net)
+		return 1;
+
+	/*
+	 * loopback traffic already labeled and
+	 * flow-controlled on outbound. We may
+	 * need to flow-control on the inbound
+	 * as well if there's ever a use-case for it.
+	 */
+	if (skb->dev == &loopback_dev)
+		return 1;
+
+	err = selinux_xfrm_decode_session(skb, &xfrm_sid, 0);
+	BUG_ON(err);
+
+	err = avc_has_perm(xfrm_sid, skb->secmark? : SECINITSID_NETMSG,
+					SECCLASS_PACKET,
+					PACKET__FLOW_IN, NULL);
+	if (err)
+		goto out;
+
+	if (xfrm_sid)
+		skb->secmark = xfrm_sid;
+
+	/* See if NetLabel can flow in thru the current secmark here */
+
+out:
+	return err ? 0 : 1;
+};
+
+static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+{
+	int err;
+
+	if (selinux_compat_net)
+		return 1;
+
+	if (!skb->secmark) {
+		u32 xfrm_sid;
+
+		selinux_skb_xfrm_sid(skb, &xfrm_sid);
+
+		if (xfrm_sid)
+			skb->secmark = xfrm_sid;
+		else if (skb->sk) {
+			struct sk_security_struct *sksec = skb->sk->sk_security;
+			skb->secmark = sksec->sid;
+		}
+	}
+
+	err = avc_has_perm(skb->secmark, nf_secid, SECCLASS_PACKET,
+				PACKET__FLOW_OUT, NULL);
+
+	return err ? 0 : 1;
+}
+
 static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
 {
 	int err = 0;
@@ -3714,7 +3788,8 @@ out:
 
 #ifdef CONFIG_NETFILTER
 
-static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
+static int selinux_ip_postroute_last_compat(struct sock *sk, struct sk_buff *skb,
+					    struct net_device *dev,
 					    struct avc_audit_data *ad,
 					    u16 family, char *addrp, int len)
 {
@@ -3724,6 +3799,9 @@ static int selinux_ip_postroute_last_com
 	struct inode *inode;
 	struct inode_security_struct *isec;
 
+	if (!sk)
+		goto out;
+
 	sock = sk->sk_socket;
 	if (!sock)
 		goto out;
@@ -3782,7 +3860,11 @@ static int selinux_ip_postroute_last_com
 
 		err = avc_has_perm(isec->sid, port_sid, isec->sclass,
 				   send_perm, ad);
+		if (err)
+			goto out;
 	}
+
+	err = selinux_xfrm_postroute_last(isec->sid, skb, ad);
 out:
 	return err;
 }
@@ -3796,17 +3878,9 @@ static unsigned int selinux_ip_postroute
 {
 	char *addrp;
 	int len, err = 0;
-	struct sock *sk;
 	struct sk_buff *skb = *pskb;
 	struct avc_audit_data ad;
 	struct net_device *dev = (struct net_device *)out;
-	struct sk_security_struct *sksec;
-
-	sk = skb->sk;
-	if (!sk)
-		goto out;
-
-	sksec = sk->sk_security;
 
 	AVC_AUDIT_DATA_INIT(&ad, NET);
 	ad.u.net.netif = dev->name;
@@ -3817,16 +3891,25 @@ static unsigned int selinux_ip_postroute
 		goto out;
 
 	if (selinux_compat_net)
-		err = selinux_ip_postroute_last_compat(sk, dev, &ad,
+		err = selinux_ip_postroute_last_compat(skb->sk, skb, dev, &ad,
 						       family, addrp, len);
-	else
-		err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
-				   PACKET__SEND, &ad);
+	else {
+		if (!skb->secmark) {
+			u32 xfrm_sid;
 
-	if (err)
-		goto out;
+			selinux_skb_xfrm_sid(skb, &xfrm_sid);
 
-	err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad);
+			if (xfrm_sid)
+				skb->secmark = xfrm_sid;
+			else if (skb->sk) {
+				struct sk_security_struct *sksec =
+						skb->sk->sk_security;
+				skb->secmark = sksec->sid;
+			}
+		}
+		err = avc_has_perm(skb->secmark, SECINITSID_NETMSG,
+				   SECCLASS_PACKET, PACKET__FLOW_OUT, &ad);
+	}
 out:
 	return err ? NF_DROP : NF_ACCEPT;
 }
@@ -4733,6 +4816,8 @@ static struct security_operations selinu
 	.inet_conn_request =		selinux_inet_conn_request,
 	.inet_csk_clone =		selinux_inet_csk_clone,
 	.req_classify_flow =		selinux_req_classify_flow,
+	.skb_flow_in =			selinux_skb_flow_in,
+	.skb_flow_out =			selinux_skb_flow_out,
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 	.xfrm_policy_alloc_security =	selinux_xfrm_policy_alloc,
Index: net-2.6_secidfinal/security/selinux/include/xfrm.h
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/include/xfrm.h
+++ net-2.6_secidfinal/security/selinux/include/xfrm.h
@@ -38,9 +38,9 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, s
 			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);
 int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
+void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid);
 #else
 static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
 			struct avc_audit_data *ad)
@@ -54,11 +54,6 @@ static inline int selinux_xfrm_postroute
 	return 0;
 }
 
-static inline int selinux_socket_getpeer_stream(struct sock *sk)
-{
-	return SECSID_NULL;
-}
-
 static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
 {
 	return SECSID_NULL;
@@ -68,6 +63,10 @@ static inline int selinux_xfrm_decode_se
 	*sid = SECSID_NULL;
 	return 0;
 }
+static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+{
+	*sid = SECSID_NULL;
+}
 #endif
 
 #endif /* _SELINUX_XFRM_H_ */
Index: net-2.6_secidfinal/security/selinux/xfrm.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/xfrm.c
+++ net-2.6_secidfinal/security/selinux/xfrm.c
@@ -155,7 +155,8 @@ int selinux_xfrm_flow_state_match(struct
 }
 
 /*
- * LSM hook implementation that determines the sid for the session.
+ * 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)
@@ -193,6 +194,32 @@ int selinux_xfrm_decode_session(struct s
 }
 
 /*
+ * LSM hook implementation that returns the xfrm sid for the outgoing packet.
+ */
+
+void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
+{
+	struct dst_entry *dst;
+
+	*sid = SECSID_NULL;
+
+	dst = skb->dst;
+	if (dst) {
+		struct dst_entry *dst_test;
+		for (dst_test = dst; dst_test != 0;
+			dst_test = dst_test->child) {
+			struct xfrm_state *x = dst_test->xfrm;
+
+			if (x && selinux_authorizable_xfrm(x)) {
+				struct xfrm_sec_ctx *ctx = x->security;
+				*sid = ctx->ctx_sid;
+				break;
+			}
+		}
+	}
+}
+
+/*
  * Security blob allocation for xfrm_policy and xfrm_state
  * CTX does not have a meaningful value on input
  */
@@ -391,43 +418,8 @@ void selinux_xfrm_state_free(struct xfrm
 }
 
 /*
- * SELinux internal function to retrieve the context of a connected
- * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security
- * association used to connect to the remote socket.
- *
- * Retrieve via getsockopt SO_PEERSEC.
- */
-u32 selinux_socket_getpeer_stream(struct sock *sk)
-{
-	struct dst_entry *dst, *dst_test;
-	u32 peer_sid = SECSID_NULL;
-
-	if (sk->sk_state != TCP_ESTABLISHED)
-		goto out;
-
-	dst = sk_dst_get(sk);
-	if (!dst)
-		goto out;
-
- 	for (dst_test = dst; dst_test != 0;
-      	     dst_test = dst_test->child) {
-		struct xfrm_state *x = dst_test->xfrm;
-
- 		if (x && selinux_authorizable_xfrm(x)) {
-	 	 	struct xfrm_sec_ctx *ctx = x->security;
-			peer_sid = ctx->ctx_sid;
-			break;
-		}
-	}
-	dst_release(dst);
-
-out:
-	return peer_sid;
-}
-
-/*
  * SELinux internal function to retrieve the context of a UDP packet
- * based on its security association used to connect to the remote socket.
+ * based on its security association.
  *
  * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message
  * type SCM_SECURITY.

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 08/11] secid reconciliation: Use secmark when classifying flow using skb
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (6 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 07/11] secid reconciliation: Enforcement for SELinux paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 09/11] secid reconciliation: Track peersecid at connection establishment paul.moore
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-8 --]
[-- Type: text/plain, Size: 2533 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

This beings secmark into the picture when classifying flows
using an skb.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 include/linux/security.h |   10 ----------
 include/linux/skbuff.h   |   20 ++++++++++++++++++++
 2 files changed, 20 insertions(+), 10 deletions(-)

Index: net-2.6_secidfinal/include/linux/security.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/security.h
+++ net-2.6_secidfinal/include/linux/security.h
@@ -3224,12 +3224,6 @@ static inline int security_xfrm_decode_s
 	return security_ops->xfrm_decode_session(skb, secid, 1);
 }
 
-static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
-{
-	int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0);
-
-	BUG_ON(rc);
-}
 #else	/* CONFIG_SECURITY_NETWORK_XFRM */
 static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
 {
@@ -3298,10 +3292,6 @@ static inline int security_xfrm_decode_s
 	return 0;
 }
 
-static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
-{
-}
-
 #endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 
 #ifdef CONFIG_KEYS
Index: net-2.6_secidfinal/include/linux/skbuff.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/skbuff.h
+++ net-2.6_secidfinal/include/linux/skbuff.h
@@ -30,6 +30,7 @@
 #include <net/checksum.h>
 #include <linux/dmaengine.h>
 #include <net/flow.h>
+#include <linux/security.h>
 
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
@@ -1514,6 +1515,20 @@ static inline void security_flow_classif
 	skb->secmark = fl->secid;
 }
 
+static inline void security_skb_classify_flow(struct sk_buff *skb,
+					struct flowi *fl)
+{
+	/*
+	 * We need to check for xfrm label here since secid reconciliation
+	 * may or may not have happened yet and we want the
+	 * flow to use the best available label.
+	 */
+	int rc = security_xfrm_decode_session(skb, &fl->secid);
+
+	if (rc || !fl->secid)
+		fl->secid = skb->secmark;
+}
+
 #else
 
 static inline void security_skb_classify_skb(struct sk_buff *from,
@@ -1526,6 +1541,11 @@ static inline void security_flow_classif
 {
 }
 
+static inline void security_skb_classify_flow(struct sk_buff *skb,
+					struct flowi *fl)
+{
+}
+
 #endif /* CONFIG_SECURITY_NETWORK */
 
 #endif	/* __KERNEL__ */

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 09/11] secid reconciliation: Track peersecid at connection establishment
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (7 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 08/11] secid reconciliation: Use secmark when classifying flow using skb paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 10/11] secid reconciliation: various fixes paul.moore
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-9 --]
[-- Type: text/plain, Size: 4603 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

This tracks the peer's secid at connection establishment time
for clients, for later retrieval using SO_PEERSEC.

Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 include/linux/security.h |   14 ++++++++++++++
 net/ipv4/tcp_input.c     |    2 ++
 security/dummy.c         |    6 ++++++
 security/selinux/hooks.c |    9 +++++++++
 4 files changed, 31 insertions(+)

Index: net-2.6_secidfinal/include/linux/security.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/security.h
+++ net-2.6_secidfinal/include/linux/security.h
@@ -826,6 +826,8 @@ struct request_sock;
  *	Sets the openreq's sid to socket's sid with MLS portion taken from peer sid.
  * @inet_csk_clone:
  *	Sets the new child socket's sid to the openreq sid.
+ * @inet_conn_established:
+ *	Sets the connection's peersid to the secmark on skb.
  * @req_classify_flow:
  *	Sets the flow's sid to the openreq sid.
  * @skb_flow_in:
@@ -1380,6 +1382,7 @@ struct security_operations {
 	int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb,
 					struct request_sock *req);
 	void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
+	void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
 	void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
 	int (*skb_flow_in)(struct sk_buff *skb, unsigned short family);
 	int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid);
@@ -2986,6 +2989,12 @@ static inline void security_inet_csk_clo
 {
 	security_ops->inet_csk_clone(newsk, req);
 }
+
+static inline void security_inet_conn_established(struct sock *sk,
+					struct sk_buff *skb)
+{
+	security_ops->inet_conn_established(sk, skb);
+}
 #else	/* CONFIG_SECURITY_NETWORK */
 static inline int security_unix_stream_connect(struct socket * sock,
 					       struct socket * other, 
@@ -3147,6 +3156,11 @@ static inline void security_inet_csk_clo
 			const struct request_sock *req)
 {
 }
+
+static inline void security_inet_conn_established(struct sock *sk,
+					struct sk_buff *skb)
+{
+}
 #endif	/* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
Index: net-2.6_secidfinal/net/ipv4/tcp_input.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/tcp_input.c
+++ net-2.6_secidfinal/net/ipv4/tcp_input.c
@@ -4230,6 +4230,8 @@ static int tcp_rcv_synsent_state_process
 		mb();
 		tcp_set_state(sk, TCP_ESTABLISHED);
 
+		security_inet_conn_established(sk, skb);
+
 		/* Make sure socket is routed, for correct metrics.  */
 		icsk->icsk_af_ops->rebuild_header(sk);
 
Index: net-2.6_secidfinal/security/dummy.c
===================================================================
--- net-2.6_secidfinal.orig/security/dummy.c
+++ net-2.6_secidfinal/security/dummy.c
@@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(
 {
 }
 
+static inline void dummy_inet_conn_established(struct sock *sk,
+			struct sk_buff *skb)
+{
+}
+
 static inline void dummy_req_classify_flow(const struct request_sock *req,
 			struct flowi *fl)
 {
@@ -1118,6 +1123,7 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, sock_graft);
 	set_to_dummy_if_null(ops, inet_conn_request);
 	set_to_dummy_if_null(ops, inet_csk_clone);
+	set_to_dummy_if_null(ops, inet_conn_established);
 	set_to_dummy_if_null(ops, req_classify_flow);
 	set_to_dummy_if_null(ops, skb_flow_in);
 	set_to_dummy_if_null(ops, skb_flow_out);
Index: net-2.6_secidfinal/security/selinux/hooks.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/hooks.c
+++ net-2.6_secidfinal/security/selinux/hooks.c
@@ -3683,6 +3683,14 @@ static void selinux_inet_csk_clone(struc
 	selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family);
 }
 
+static void selinux_inet_conn_established(struct sock *sk,
+				   struct sk_buff *skb)
+{
+	struct sk_security_struct *sksec = sk->sk_security;
+
+	sksec->peer_sid = skb->secmark;
+}
+
 static void selinux_req_classify_flow(const struct request_sock *req,
 				      struct flowi *fl)
 {
@@ -4815,6 +4823,7 @@ static struct security_operations selinu
 	.sock_graft =			selinux_sock_graft,
 	.inet_conn_request =		selinux_inet_conn_request,
 	.inet_csk_clone =		selinux_inet_csk_clone,
+	.inet_conn_established =	selinux_inet_conn_established,
 	.req_classify_flow =		selinux_req_classify_flow,
 	.skb_flow_in =			selinux_skb_flow_in,
 	.skb_flow_out =			selinux_skb_flow_out,

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 10/11] secid reconciliation: various fixes
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (8 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 09/11] secid reconciliation: Track peersecid at connection establishment paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 19:42 ` [PATCH 11/11] secid reconciliation: support for NetLabel paul.moore
  2006-10-09 20:19 ` [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) James Morris
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds

[-- Attachment #1: secid-fix_1 --]
[-- Type: text/plain, Size: 17809 bytes --]

From: Venkat Yekkirala <vyekkirala@TrustedCS.com>

This fixes the secid reconciliation code in the following ways:

1. Null-out secmark on an outgoing packet after we are done with all
   the checks. This has been necessitated by the fact that some packets
   sent to a multicast address could arrive back on a non-loopback
   interface but with the secmark intact. This would result in the
   current flow_out control logic to use it as a security point context
   when no explicit security points have been defined for the inbound
   packet.

2. Label udp/raw packets with the label of the socket.

3. Label igmp traffic with the igmp_packet initial context.

4. Limit flow-controlling of loopback traffic to the socket.recv permission
   check. This means that packet.flow_in/flow_out checks are no longer
   applicable to loopback traffic. This is because of current implementation
   constraints.


DOCUMENTATION OF SECID RECONCILIATION AND FLOW CONTROL FOR POLICY WRITERS:

ON INBOUND:

1. PACKETS ENTERING SYSTEM FROM A NON-LOOPBACK DEVICE:

   Can a packet "carrying" external domain label x_t "flow_in" thru the
   security point with the peer domain label p_d_t?

	NOTE:
	a. x_t defaults to unlabeled_t, if no external label.
	b. p_d_t defaults to network_t in the absence of any applicable
	   [conn]secmark rules for the packet. If there are multiple
	   secmark rules applicable to a packet, the context on the LAST
	   rule will apply.

   NO: Drop packet.
   YES: If no external label, let packet "carry" p_d_t.

2. INPUT ONLY: Can a socket "recv" a packet from domain p_d_t?

   NO: Drop packet.
   YES: If setting up a tcp connection, set peer context to p_d_t.

ON OUTBOUND:

1. Let packet "carry" the originating socket domain label.

2. IPSEC Handling:

   LABELED IPSEC: If packet "polmatch"es to an otherwise applicable and
   labeled SPD entry, choose a Security Association (SA) with the SAME context
   as the domain label being carried by packet.
	NOTE: If no such SA present, call into IKE with context on packet.

   NON-LABELED (PLAIN/TRADITIONAL) IPSEC: If there's an applicable SPD entry
   that does NOT have an explicit context associated with it, an applicable SA
   that does NOT have an explicit context associated with it is chosen.
	NOTE: If no such SA present, call into IKE, but with NO context.

3. PACKETS DESTINED FOR NON-LOOPBACK DEVICE:

   a. IPTABLES Processing:
      As EACH applicable iptables [CONN]SECMARK rule with domain p_d_t is
      encountered, do the following:
   
      Can a packet carrying domain label a_t "flow_out" of the security point
      with the domain label p_d_t?
   
         NO: Drop packet.
         YES: Replace the domain label a_t on the packet with the security point
              label p_d_t.

   b. Before a packet is let out of the system:

      Can a packet with domain label p_d_t "flow_out" into the network domain
      network_t?

      NO: Drop packet.
      YES: Let packet out.

      NOTE: Ideally this check should be applicable only to packets that
            didn't go thru [conn]secmark checks for outbound, but there's
            currently no way to know this due to implementation constrains.
            Hence a blanket check for ALL packets leaving the system.

FORWARDED TRAFFIC:

Forwarded Traffic will undergo the following:

1. Step 1 under ON INBOUND.

2. Steps 2 and 3 under ON OUTBOUND.


Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com>
---
 include/linux/security.h       |   24 +++++++++-------
 include/net/ip.h               |   13 ++++++++
 include/net/request_sock.h     |   11 +++++++
 net/ipv4/igmp.c                |    4 ++
 net/ipv4/raw.c                 |    2 +
 net/ipv4/udp.c                 |    2 +
 net/netfilter/xt_CONNSECMARK.c |   21 ++++++++++----
 net/netfilter/xt_SECMARK.c     |   16 ++++++++--
 security/dummy.c               |    8 ++---
 security/selinux/hooks.c       |   61 +++++++++++++++++++++++++++++++++--------
 10 files changed, 129 insertions(+), 33 deletions(-)

Index: net-2.6_secidfinal/include/linux/security.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/security.h
+++ net-2.6_secidfinal/include/linux/security.h
@@ -67,6 +67,7 @@ struct xfrm_selector;
 struct xfrm_policy;
 struct xfrm_state;
 struct xfrm_user_sec_ctx;
+struct net_device;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
@@ -828,8 +829,8 @@ struct request_sock;
  *	Sets the new child socket's sid to the openreq sid.
  * @inet_conn_established:
  *	Sets the connection's peersid to the secmark on skb.
- * @req_classify_flow:
- *	Sets the flow's sid to the openreq sid.
+ * @igmp_classify_skb:
+ *	Classifies an skb representing an igmp packet.
  * @skb_flow_in:
  *	Checks to see if security policy would allow skb into the system
  *	while also reconciling the xfrm secid, cipso, etc, if any, and
@@ -1383,9 +1384,10 @@ struct security_operations {
 					struct request_sock *req);
 	void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
 	void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
-	void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
+	void (*igmp_classify_skb)(struct sk_buff *skb);
 	int (*skb_flow_in)(struct sk_buff *skb, unsigned short family);
-	int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid);
+	int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid,
+			const struct net_device *out, unsigned short family);
 #endif	/* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2956,9 +2958,9 @@ static inline void security_sk_classify_
 	security_ops->sk_getsecid(sk, &fl->secid);
 }
 
-static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
+static inline void security_igmp_classify_skb(struct sk_buff *skb)
 {
-	security_ops->req_classify_flow(req, fl);
+	security_ops->igmp_classify_skb(skb);
 }
 
 static inline int security_skb_flow_in(struct sk_buff *skb,
@@ -2968,9 +2970,10 @@ static inline int security_skb_flow_in(s
 }
 
 static inline int security_skb_flow_out(struct sk_buff *skb,
-					u32 nf_secid)
+			u32 nf_secid, const struct net_device *out,
+			unsigned short family)
 {
-	return security_ops->skb_flow_out(skb, nf_secid);
+	return security_ops->skb_flow_out(skb, nf_secid, out, family);
 }
 
 static inline void security_sock_graft(struct sock* sk, struct socket *parent)
@@ -3126,7 +3129,7 @@ static inline void security_sk_classify_
 {
 }
 
-static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
+static inline void security_igmp_classify_skb(struct sk_buff *skb)
 {
 }
 
@@ -3137,7 +3140,8 @@ static inline int security_skb_flow_in(s
 }
 
 static inline int security_skb_flow_out(struct sk_buff *skb,
-					u32 nf_secid)
+			u32 nf_secid, const struct net_device *out,
+			unsigned short family)
 {
 	return -ENOENT;
 }
Index: net-2.6_secidfinal/include/net/ip.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/ip.h
+++ net-2.6_secidfinal/include/net/ip.h
@@ -388,6 +388,14 @@ extern struct ctl_table ipv4_table[];
 
 #ifdef CONFIG_SECURITY_NETWORK
 
+extern struct security_operations *security_ops;
+
+static inline void security_sk_classify_ipcm(struct sock *sk,
+				struct ipcm_cookie *ipc)
+{
+	security_ops->sk_getsecid(sk, &ipc->secid);
+}
+
 static inline void security_skb_classify_ipcm(struct sk_buff *skb,
 					struct ipcm_cookie *ipc)
 {
@@ -402,6 +410,11 @@ static inline void security_ipcm_classif
 
 #else
 
+static inline void security_sk_classify_ipcm(struct sock *sk,
+				struct ipcm_cookie *ipc)
+{
+}
+
 static inline void security_skb_classify_ipcm(struct sk_buff *skb,
 					struct ipcm_cookie *ipc)
 {
Index: net-2.6_secidfinal/include/net/request_sock.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/request_sock.h
+++ net-2.6_secidfinal/include/net/request_sock.h
@@ -262,6 +262,12 @@ static inline void reqsk_queue_hash_req(
 
 #ifdef CONFIG_SECURITY_NETWORK
 
+static inline void security_req_classify_flow(const struct request_sock *req,
+					struct flowi *fl)
+{
+	fl->secid = req->secid;
+}
+
 static inline void security_req_classify_skb(struct request_sock *req,
 					struct sk_buff *skb)
 {
@@ -270,6 +276,11 @@ static inline void security_req_classify
 
 #else
 
+static inline void security_req_classify_flow(const struct request_sock *req,
+					struct flowi *fl)
+{
+}
+
 static inline void security_req_classify_skb(struct request_sock *req,
 					struct sk_buff *skb)
 {
Index: net-2.6_secidfinal/net/ipv4/igmp.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/igmp.c
+++ net-2.6_secidfinal/net/ipv4/igmp.c
@@ -293,6 +293,8 @@ static struct sk_buff *igmpv3_newpack(st
 	if (skb == NULL)
 		return NULL;
 
+	security_igmp_classify_skb(skb);
+
 	{
 		struct flowi fl = { .oif = dev->ifindex,
 				    .nl_u = { .ip4_u = {
@@ -658,6 +660,8 @@ static int igmp_send_report(struct in_de
 		return -1;
 	}
 
+	security_igmp_classify_skb(skb);
+
 	skb->dst = &rt->u.dst;
 
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
Index: net-2.6_secidfinal/net/ipv4/raw.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/raw.c
+++ net-2.6_secidfinal/net/ipv4/raw.c
@@ -433,6 +433,8 @@ static int raw_sendmsg(struct kiocb *ioc
 	ipc.opt = NULL;
 	ipc.oif = sk->sk_bound_dev_if;
 
+	security_sk_classify_ipcm(sk, &ipc);
+
 	if (msg->msg_controllen) {
 		err = ip_cmsg_send(msg, &ipc);
 		if (err)
Index: net-2.6_secidfinal/net/ipv4/udp.c
===================================================================
--- net-2.6_secidfinal.orig/net/ipv4/udp.c
+++ net-2.6_secidfinal/net/ipv4/udp.c
@@ -588,6 +588,8 @@ int udp_sendmsg(struct kiocb *iocb, stru
 	if (!ipc.opt)
 		ipc.opt = inet->opt;
 
+	security_sk_classify_ipcm(sk, &ipc);
+
 	saddr = ipc.addr;
 	ipc.addr = faddr = daddr;
 
Index: net-2.6_secidfinal/net/netfilter/xt_CONNSECMARK.c
===================================================================
--- net-2.6_secidfinal.orig/net/netfilter/xt_CONNSECMARK.c
+++ net-2.6_secidfinal/net/netfilter/xt_CONNSECMARK.c
@@ -68,7 +68,8 @@ static void secmark_save(struct sk_buff 
  * On the outbound, filter based on the current secmark.
  */
 static unsigned int secmark_restore(struct sk_buff *skb, unsigned int hooknum,
-		   const struct net_device *in, unsigned short family)
+		   const struct net_device *in, const struct net_device *out,
+		   unsigned short family)
 {
 	u32 *psecmark;
 	enum ip_conntrack_info ctinfo;
@@ -81,14 +82,24 @@ static unsigned int secmark_restore(stru
 		if (outbound(family, hooknum)) {
 			int err;
 
-			err = security_skb_flow_out(skb, *psecmark);
+			/*
+			 * We can't currently flow-control loopback traffic
+			 * very well since we want to retain the secmark of
+			 * the originating socket and if we do retain it,
+			 * it will cause connsecmark save & restore to use this
+			 * socket label and mess up the semantics of the "peer
+			 * security point".
+			 */
+			if (out == &loopback_dev)
+				goto out;
+
+			err = security_skb_flow_out(skb, *psecmark, out, family);
 			if (!err)
 				return NF_DROP;
 		} else
 			/* 
 			 * inbound:
-			 * loopback traffic should already be labeled
-			 * and any filtering on outbound should suffice
+			 * No filtering of loopback traffic.
 			 */
 			if (in == &loopback_dev)
 				goto out;
@@ -119,7 +130,7 @@ static unsigned int target(struct sk_buf
 		break;
 
 	case CONNSECMARK_RESTORE:
-		return secmark_restore(skb, hooknum, in, target->family);
+		return secmark_restore(skb, hooknum, in, out, target->family);
 		break;
 
 	default:
Index: net-2.6_secidfinal/net/netfilter/xt_SECMARK.c
===================================================================
--- net-2.6_secidfinal.orig/net/netfilter/xt_SECMARK.c
+++ net-2.6_secidfinal/net/netfilter/xt_SECMARK.c
@@ -70,14 +70,24 @@ static unsigned int target(struct sk_buf
 		if (outbound(target->family, hooknum)) {
 			int err;
 
-			err = security_skb_flow_out(*pskb, secmark);
+			/*
+			 * We can't currently flow-control loopback traffic
+			 * very well since we want to retain the secmark of
+			 * the originating socket and if we do retain it,
+			 * it will cause connsecmark save & restore to use this
+			 * socket label and mess up the semantics of the "peer
+			 * security point".
+			 */
+			if (out == &loopback_dev)
+				goto out;
+
+			err = security_skb_flow_out(*pskb, secmark, out, target->family);
 			if (!err)
 				return NF_DROP;
 		} else
 			/*
 			 * inbound:
-			 * loopback traffic should already be labeled
-			 * and any filtering on outbound should suffice
+			 * No filtering of loopback traffic.
 			 */
 			if (in == &loopback_dev)
 				goto out;
Index: net-2.6_secidfinal/security/dummy.c
===================================================================
--- net-2.6_secidfinal.orig/security/dummy.c
+++ net-2.6_secidfinal/security/dummy.c
@@ -833,8 +833,7 @@ static inline void dummy_inet_conn_estab
 {
 }
 
-static inline void dummy_req_classify_flow(const struct request_sock *req,
-			struct flowi *fl)
+static inline void dummy_igmp_classify_skb(struct sk_buff *skb)
 {
 }
 
@@ -844,7 +843,8 @@ static inline int dummy_skb_flow_in(stru
 	return -ENOENT;
 }
 
-static inline int dummy_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+static inline int dummy_skb_flow_out(struct sk_buff *skb, u32 nf_secid,
+			const struct net_device *out, unsigned short family)
 {
 	return -ENOENT;
 }
@@ -1124,7 +1124,7 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, inet_conn_request);
 	set_to_dummy_if_null(ops, inet_csk_clone);
 	set_to_dummy_if_null(ops, inet_conn_established);
-	set_to_dummy_if_null(ops, req_classify_flow);
+	set_to_dummy_if_null(ops, igmp_classify_skb);
 	set_to_dummy_if_null(ops, skb_flow_in);
 	set_to_dummy_if_null(ops, skb_flow_out);
  #endif	/* CONFIG_SECURITY_NETWORK */
Index: net-2.6_secidfinal/security/selinux/hooks.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/hooks.c
+++ net-2.6_secidfinal/security/selinux/hooks.c
@@ -3691,35 +3691,42 @@ static void selinux_inet_conn_establishe
 	sksec->peer_sid = skb->secmark;
 }
 
-static void selinux_req_classify_flow(const struct request_sock *req,
-				      struct flowi *fl)
+static void selinux_igmp_classify_skb(struct sk_buff *skb)
 {
-	fl->secid = req->secid;
+	skb->secmark = SECINITSID_IGMP_PACKET;
 }
 
 static int selinux_skb_flow_in(struct sk_buff *skb, unsigned short family)
 {
 	u32 xfrm_sid;
 	int err;
+	struct avc_audit_data ad;
+	char *addrp;
+	int len;
 
 	if (selinux_compat_net)
 		return 1;
 
 	/*
-	 * loopback traffic already labeled and
-	 * flow-controlled on outbound. We may
-	 * need to flow-control on the inbound
-	 * as well if there's ever a use-case for it.
+	 * loopback traffic should already be labeled with
+	 * the originating socket label.
 	 */
 	if (skb->dev == &loopback_dev)
 		return 1;
 
+	AVC_AUDIT_DATA_INIT(&ad, NET);
+	ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
+	ad.u.net.family = family;
+	err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+	if (err)
+		goto out;
+
 	err = selinux_xfrm_decode_session(skb, &xfrm_sid, 0);
 	BUG_ON(err);
 
 	err = avc_has_perm(xfrm_sid, skb->secmark? : SECINITSID_NETMSG,
 					SECCLASS_PACKET,
-					PACKET__FLOW_IN, NULL);
+					PACKET__FLOW_IN, &ad);
 	if (err)
 		goto out;
 
@@ -3732,9 +3739,14 @@ out:
 	return err ? 0 : 1;
 };
 
-static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid)
+static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid,
+			const struct net_device *out, unsigned short family)
 {
 	int err;
+	char *addrp;
+	int len;
+	struct net_device *dev = (struct net_device *)out;
+	struct avc_audit_data ad;
 
 	if (selinux_compat_net)
 		return 1;
@@ -3752,9 +3764,17 @@ static int selinux_skb_flow_out(struct s
 		}
 	}
 
+	AVC_AUDIT_DATA_INIT(&ad, NET);
+	ad.u.net.netif = dev->name;
+	ad.u.net.family = family;
+	err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+	if (err)
+		goto out;
+
 	err = avc_has_perm(skb->secmark, nf_secid, SECCLASS_PACKET,
-				PACKET__FLOW_OUT, NULL);
+				PACKET__FLOW_OUT, &ad);
 
+out:
 	return err ? 0 : 1;
 }
 
@@ -3915,8 +3935,27 @@ static unsigned int selinux_ip_postroute
 				skb->secmark = sksec->sid;
 			}
 		}
+		if (out == &loopback_dev)
+			return NF_ACCEPT;
+
 		err = avc_has_perm(skb->secmark, SECINITSID_NETMSG,
 				   SECCLASS_PACKET, PACKET__FLOW_OUT, &ad);
+
+		if (skb->secmark)
+			/*
+			 * Our multicast packets could get copied back
+			 * to us, arriving on a non-loopback device.
+			 * Leaving the secmark intact here will cause it
+			 * to be used as a security point context in
+			 * the flow_in hook above while it's not in fact
+			 * a security point context.
+			 *
+			 * We may be able to retain this marking if
+			 * we can reliably determine that it was a local
+			 * packet although it arrived on a non-loopback
+			 * device, in the flow_in hook above.
+			 */
+			skb->secmark = SECSID_NULL;
 	}
 out:
 	return err ? NF_DROP : NF_ACCEPT;
@@ -4824,7 +4863,7 @@ static struct security_operations selinu
 	.inet_conn_request =		selinux_inet_conn_request,
 	.inet_csk_clone =		selinux_inet_csk_clone,
 	.inet_conn_established =	selinux_inet_conn_established,
-	.req_classify_flow =		selinux_req_classify_flow,
+	.igmp_classify_skb =		selinux_igmp_classify_skb,
 	.skb_flow_in =			selinux_skb_flow_in,
 	.skb_flow_out =			selinux_skb_flow_out,
 

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 11/11] secid reconciliation: support for NetLabel
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (9 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 10/11] secid reconciliation: various fixes paul.moore
@ 2006-10-09 19:42 ` paul.moore
  2006-10-09 20:19 ` [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) James Morris
  11 siblings, 0 replies; 17+ messages in thread
From: paul.moore @ 2006-10-09 19:42 UTC (permalink / raw)
  To: netdev, selinux; +Cc: vyekkirala, jmorris, sds, Paul Moore

[-- Attachment #1: secid-netlabel --]
[-- Type: text/plain, Size: 21147 bytes --]

From: Paul Moore <paul.moore@hp.com>

This patch provides the missing NetLabel support to the secid reconciliation
patchset.

This includes a change to the security_skb_flow_in() LSM hook to indicate if
the hook is in the forwarding path and a change to netlbl_skbuff_err() to carry
the forwarding information to the lower protocol level.  This was required to
meet the CIPSO specifications regarding handling permission denied errors.

Signed-off-by: Paul Moore <paul.moore@hp.com>
---
 include/linux/security.h                    |   10 +-
 include/net/netlabel.h                      |    6 -
 include/net/xfrm.h                          |    4 
 net/netlabel/netlabel_kapi.c                |    5 -
 security/dummy.c                            |    3 
 security/selinux/hooks.c                    |  139 +++++++++++++++++++---------
 security/selinux/include/objsec.h           |    1 
 security/selinux/include/selinux_netlabel.h |   34 ++----
 security/selinux/ss/services.c              |  124 ++++--------------------
 9 files changed, 153 insertions(+), 173 deletions(-)

Index: net-2.6_secidfinal/include/linux/security.h
===================================================================
--- net-2.6_secidfinal.orig/include/linux/security.h
+++ net-2.6_secidfinal/include/linux/security.h
@@ -1385,7 +1385,7 @@ struct security_operations {
 	void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
 	void (*inet_conn_established)(struct sock *sk, struct sk_buff *skb);
 	void (*igmp_classify_skb)(struct sk_buff *skb);
-	int (*skb_flow_in)(struct sk_buff *skb, unsigned short family);
+	int (*skb_flow_in)(struct sk_buff *skb, unsigned short family, u32 fwd);
 	int (*skb_flow_out)(struct sk_buff *skb, u32 nf_secid,
 			const struct net_device *out, unsigned short family);
 #endif	/* CONFIG_SECURITY_NETWORK */
@@ -2964,9 +2964,10 @@ static inline void security_igmp_classif
 }
 
 static inline int security_skb_flow_in(struct sk_buff *skb,
-					unsigned short family)
+				       unsigned short family,
+				       u32 fwd)
 {
-	return security_ops->skb_flow_in(skb, family);
+	return security_ops->skb_flow_in(skb, family, fwd);
 }
 
 static inline int security_skb_flow_out(struct sk_buff *skb,
@@ -3134,7 +3135,8 @@ static inline void security_igmp_classif
 }
 
 static inline int security_skb_flow_in(struct sk_buff *skb,
-					unsigned short family)
+				       unsigned short family,
+				       u32 fwd)
 {
 	return 1;
 }
Index: net-2.6_secidfinal/include/net/netlabel.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/netlabel.h
+++ net-2.6_secidfinal/include/net/netlabel.h
@@ -237,7 +237,7 @@ int netlbl_socket_getattr(const struct s
 			  struct netlbl_lsm_secattr *secattr);
 int netlbl_skbuff_getattr(const struct sk_buff *skb,
 			  struct netlbl_lsm_secattr *secattr);
-void netlbl_skbuff_err(struct sk_buff *skb, int error);
+void netlbl_skbuff_err(struct sk_buff *skb, int error, u32 gateway);
 #else
 static inline int netlbl_socket_setattr(const struct socket *sock,
 				     const struct netlbl_lsm_secattr *secattr)
@@ -263,7 +263,9 @@ static inline int netlbl_skbuff_getattr(
 	return -ENOSYS;
 }
 
-static inline void netlbl_skbuff_err(struct sk_buff *skb, int error)
+static inline void netlbl_skbuff_err(struct sk_buff *skb,
+				     int error,
+				     u32 gateway)
 {
 	return;
 }
Index: net-2.6_secidfinal/include/net/xfrm.h
===================================================================
--- net-2.6_secidfinal.orig/include/net/xfrm.h
+++ net-2.6_secidfinal/include/net/xfrm.h
@@ -685,7 +685,9 @@ static inline int xfrm_policy_check(stru
 		      __xfrm_policy_check(sk, dir, skb, family);
 
 	if (ret)
-		ret = security_skb_flow_in(skb, family);
+		ret = security_skb_flow_in(skb,
+					   family,
+					   dir == XFRM_POLICY_FWD ? 1 : 0);
 	return ret;
 }
 
Index: net-2.6_secidfinal/net/netlabel/netlabel_kapi.c
===================================================================
--- net-2.6_secidfinal.orig/net/netlabel/netlabel_kapi.c
+++ net-2.6_secidfinal/net/netlabel/netlabel_kapi.c
@@ -159,6 +159,7 @@ int netlbl_skbuff_getattr(const struct s
  * netlbl_skbuff_err - Handle a LSM error on a sk_buff
  * @skb: the packet
  * @error: the error code
+ * @gateway: true if the packet is being forwarded and not consumed locally
  *
  * Description:
  * Deal with a LSM problem when handling the packet in @skb, typically this is
@@ -166,10 +167,10 @@ int netlbl_skbuff_getattr(const struct s
  * according to the packet's labeling protocol.
  *
  */
-void netlbl_skbuff_err(struct sk_buff *skb, int error)
+void netlbl_skbuff_err(struct sk_buff *skb, int error, u32 gateway)
 {
 	if (CIPSO_V4_OPTEXIST(skb))
-		cipso_v4_error(skb, error, 0);
+		cipso_v4_error(skb, error, gateway);
 }
 
 /**
Index: net-2.6_secidfinal/security/dummy.c
===================================================================
--- net-2.6_secidfinal.orig/security/dummy.c
+++ net-2.6_secidfinal/security/dummy.c
@@ -838,7 +838,8 @@ static inline void dummy_igmp_classify_s
 }
 
 static inline int dummy_skb_flow_in(struct sk_buff *skb,
-			unsigned short family)
+				    unsigned short family,
+				    u32 fwd)
 {
 	return -ENOENT;
 }
Index: net-2.6_secidfinal/security/selinux/hooks.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/hooks.c
+++ net-2.6_secidfinal/security/selinux/hooks.c
@@ -50,6 +50,7 @@
 #include <net/icmp.h>
 #include <net/ip.h>		/* for sysctl_local_port_range[] */
 #include <net/tcp.h>		/* struct or_callable used in sock_rcv_skb */
+#include <net/netlabel.h>
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
 #include <linux/bitops.h>
@@ -3465,6 +3466,10 @@ static int selinux_sock_rcv_skb_compat(s
 			goto out;
 	}
 
+	err = selinux_netlbl_sock_rcv_skb(sock_sid, sock_class, skb, ad);
+	if (err)
+		goto out;
+
 	err = selinux_xfrm_sock_rcv_skb(sock_sid, skb, ad);
 
 out:
@@ -3498,13 +3503,15 @@ static int selinux_socket_sock_rcv_skb(s
 	if (selinux_compat_net)
 		err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family,
 						  addrp, len);
-	else
+	else {
 		err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
 				   PACKET__RECV, &ad);
-	if (err)
-		goto out;
+		if (err)
+			/* This is okay because NetLabel will only act here
+			 * if the packet is labeled with NetLabel already. */
+			netlbl_skbuff_err(skb, err, 0);
+	}
 
-	err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad);
 out:	
 	return err;
 }
@@ -3527,11 +3534,8 @@ static int selinux_socket_getpeersec_str
 		peer_sid = ssec->peer_sid;
 	}
 	else if (isec->sclass == SECCLASS_TCP_SOCKET) {
-		peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
-		if (peer_sid == SECSID_NULL) {
-			ssec = sock->sk->sk_security;
-			peer_sid = ssec->peer_sid;
-		}
+		ssec = sock->sk->sk_security;
+		peer_sid = ssec->peer_sid;
 		if (peer_sid == SECSID_NULL) {
 			err = -ENOPROTOOPT;
 			goto out;
@@ -3573,13 +3577,17 @@ static int selinux_socket_getpeersec_dgr
 	if (sock && (sock->sk->sk_family == PF_UNIX))
 		selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
 	else if (skb) {
-		peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb);
-		if (peer_secid == SECSID_NULL) {
-			if (selinux_compat_net)
-				peer_secid = selinux_socket_getpeer_dgram(skb);
-			else
-				peer_secid = skb->secmark;
-		}
+		if (selinux_compat_net) {
+			u32 xfrm_peer_secid;
+
+			xfrm_peer_secid = selinux_socket_getpeer_dgram(skb);
+			err = selinux_netlbl_skb_sid(skb,
+						     xfrm_peer_secid,
+						     &peer_secid);
+			if (err == 0 && peer_secid == SECSID_NULL)
+				peer_secid = xfrm_peer_secid;
+		} else
+			peer_secid = skb->secmark;
 	}
 
 	if (peer_secid == SECSID_NULL)
@@ -3641,13 +3649,11 @@ static int selinux_inet_conn_request(str
 	u32 newsid;
 	u32 peersid;
 
-	newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid);
-	if (newsid != SECSID_NULL) {
-		req->secid = newsid;
-		return 0;
-	}
-
 	if (selinux_compat_net) {
+		err = selinux_netlbl_skb_sid(skb, sksec->sid, &peersid);
+		if (err == 0 && peersid != SECSID_NULL)
+			goto out;
+
 		err = selinux_xfrm_decode_session(skb, &peersid, 0);
 		BUG_ON(err);
 
@@ -3659,6 +3665,7 @@ static int selinux_inet_conn_request(str
 	} else
 		peersid = skb->secmark;
 
+out:
 	err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
 	if (err)
 		return err;
@@ -3696,9 +3703,14 @@ static void selinux_igmp_classify_skb(st
 	skb->secmark = SECINITSID_IGMP_PACKET;
 }
 
-static int selinux_skb_flow_in(struct sk_buff *skb, unsigned short family)
+static int selinux_skb_flow_in(struct sk_buff *skb,
+			       unsigned short family,
+			       u32 fwd)
 {
 	u32 xfrm_sid;
+	u32 nlbl_sid;
+	u32 nlbl_base_sid;
+	u32 ext_sid;
 	int err;
 	struct avc_audit_data ad;
 	char *addrp;
@@ -3724,20 +3736,38 @@ static int selinux_skb_flow_in(struct sk
 	err = selinux_xfrm_decode_session(skb, &xfrm_sid, 0);
 	BUG_ON(err);
 
-	err = avc_has_perm(xfrm_sid, skb->secmark? : SECINITSID_NETMSG,
-					SECCLASS_PACKET,
-					PACKET__FLOW_IN, &ad);
+	if (xfrm_sid)
+		nlbl_base_sid = xfrm_sid;
+	else if (skb->secmark)
+		nlbl_base_sid = skb->secmark;
+	else
+		nlbl_base_sid = SECINITSID_UNLABELED;
+	err = selinux_netlbl_skb_sid(skb, nlbl_base_sid, &nlbl_sid);
 	if (err)
 		goto out;
 
-	if (xfrm_sid)
-		skb->secmark = xfrm_sid;
+	if (nlbl_sid)
+		ext_sid = nlbl_sid;
+	else
+		ext_sid = xfrm_sid;
 
-	/* See if NetLabel can flow in thru the current secmark here */
+	err = avc_has_perm(ext_sid,
+			   skb->secmark ? skb->secmark : SECINITSID_NETMSG,
+			   SECCLASS_PACKET,
+			   PACKET__FLOW_IN,
+			   &ad);
+	if (err) {
+		if (nlbl_sid)
+			netlbl_skbuff_err(skb, err, fwd);
+		goto out;
+	}
+
+	if (ext_sid)
+		skb->secmark = ext_sid;
 
 out:
 	return err ? 0 : 1;
-};
+}
 
 static int selinux_skb_flow_out(struct sk_buff *skb, u32 nf_secid,
 			const struct net_device *out, unsigned short family)
@@ -3752,16 +3782,30 @@ static int selinux_skb_flow_out(struct s
 		return 1;
 
 	if (!skb->secmark) {
+		u32 sk_sid;
 		u32 xfrm_sid;
+		u32 nlbl_sid;
+
+		if (skb->sk) {
+			struct sk_security_struct *sksec =
+				                          skb->sk->sk_security;
+			sk_sid = sksec->sid;
+		} else
+			sk_sid = SECSID_NULL;
 
 		selinux_skb_xfrm_sid(skb, &xfrm_sid);
+		err = selinux_netlbl_skb_sid(skb,
+					     xfrm_sid ? xfrm_sid : sk_sid,
+					     &nlbl_sid);
+		if (err)
+			goto out;
 
-		if (xfrm_sid)
+		if (nlbl_sid)
+			skb->secmark = nlbl_sid;
+		else if (xfrm_sid)
 			skb->secmark = xfrm_sid;
-		else if (skb->sk) {
-			struct sk_security_struct *sksec = skb->sk->sk_security;
-			skb->secmark = sksec->sid;
-		}
+		else if (sk_sid)
+			skb->secmark = sk_sid;
 	}
 
 	AVC_AUDIT_DATA_INIT(&ad, NET);
@@ -3923,17 +3967,30 @@ static unsigned int selinux_ip_postroute
 						       family, addrp, len);
 	else {
 		if (!skb->secmark) {
+			u32 sk_sid;
 			u32 xfrm_sid;
+			u32 nlbl_sid;
+
+			if (skb->sk) {
+				struct sk_security_struct *sksec =
+					                  skb->sk->sk_security;
+				sk_sid = sksec->sid;
+			} else
+				sk_sid = SECSID_NULL;
 
 			selinux_skb_xfrm_sid(skb, &xfrm_sid);
+			err = selinux_netlbl_skb_sid(skb,
+						  xfrm_sid ? xfrm_sid : sk_sid,
+						  &nlbl_sid);
+			if (err)
+				goto out;
 
-			if (xfrm_sid)
+			if (nlbl_sid)
+				skb->secmark = nlbl_sid;
+			else if (xfrm_sid)
 				skb->secmark = xfrm_sid;
-			else if (skb->sk) {
-				struct sk_security_struct *sksec =
-						skb->sk->sk_security;
-				skb->secmark = sksec->sid;
-			}
+			else if (sk_sid)
+				skb->secmark = sk_sid;
 		}
 		if (out == &loopback_dev)
 			return NF_ACCEPT;
Index: net-2.6_secidfinal/security/selinux/include/objsec.h
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/include/objsec.h
+++ net-2.6_secidfinal/security/selinux/include/objsec.h
@@ -102,7 +102,6 @@ struct sk_security_struct {
 	u32 sid;			/* SID of this object */
 	u32 peer_sid;			/* SID of peer */
 #ifdef CONFIG_NETLABEL
-	u16 sclass;			/* sock security class */
 	enum {				/* NetLabel state */
 		NLBL_UNSET = 0,
 		NLBL_REQUIRE,
Index: net-2.6_secidfinal/security/selinux/include/selinux_netlabel.h
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/include/selinux_netlabel.h
+++ net-2.6_secidfinal/security/selinux/include/selinux_netlabel.h
@@ -42,17 +42,16 @@ int selinux_netlbl_socket_post_create(st
 				      int sock_family,
 				      u32 sid);
 void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
-u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid);
-int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
+int selinux_netlbl_sock_rcv_skb(u32 sock_sid,
+				u16 sock_class,
 				struct sk_buff *skb,
 				struct avc_audit_data *ad);
-u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock);
-u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb);
 void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
 				     int family);
 void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
 				      struct sk_security_struct *newssec);
 int selinux_netlbl_inode_permission(struct inode *inode, int mask);
+int selinux_netlbl_skb_sid(struct sk_buff *skb, u32 base_sid, u32 *sid);
 #else
 static inline void selinux_netlbl_cache_invalidate(void)
 {
@@ -72,29 +71,14 @@ static inline void selinux_netlbl_sock_g
 	return;
 }
 
-static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb,
-						   u32 sock_sid)
-{
-	return SECSID_NULL;
-}
-
-static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
+static inline int selinux_netlbl_sock_rcv_skb(u32 sock_sid,
+					      u16 sock_class,
 					      struct sk_buff *skb,
 					      struct avc_audit_data *ad)
 {
 	return 0;
 }
 
-static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
-{
-	return SECSID_NULL;
-}
-
-static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
-{
-	return SECSID_NULL;
-}
-
 static inline void selinux_netlbl_sk_security_init(
 	                                       struct sk_security_struct *ssec,
 					       int family)
@@ -114,6 +98,14 @@ static inline int selinux_netlbl_inode_p
 {
 	return 0;
 }
+
+static inline int selinux_netlbl_skb_sid(struct sk_buff *skb,
+					 u32 base_sid,
+					 u32 *sid)
+{
+	*sid = SECSID_NULL;
+	return 0;
+}
 #endif /* CONFIG_NETLABEL */
 
 #endif
Index: net-2.6_secidfinal/security/selinux/ss/services.c
===================================================================
--- net-2.6_secidfinal.orig/security/selinux/ss/services.c
+++ net-2.6_secidfinal/security/selinux/ss/services.c
@@ -51,6 +51,7 @@
 #include "selinux_netlabel.h"
 
 extern void selnl_notify_policyload(u32 seqno);
+extern int selinux_compat_net;
 unsigned int policydb_loaded_version;
 
 static DEFINE_RWLOCK(policy_rwlock);
@@ -2336,7 +2337,7 @@ static int selinux_netlbl_secattr_to_sid
 			selinux_netlbl_cache_add(skb, &ctx_new);
 		ebitmap_destroy(&ctx_new.range.level[0].cat);
 	} else {
-		*sid = SECINITSID_UNLABELED;
+		*sid = SECSID_NULL;
 		rc = 0;
 	}
 
@@ -2349,7 +2350,7 @@ netlbl_secattr_to_sid_return_cleanup:
 }
 
 /**
- * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
+ * selinux_netlbl_skb_sid - Get the SID of a packet using NetLabel
  * @skb: the packet
  * @base_sid: the SELinux SID to use as a context for MLS only attributes
  * @sid: the SID
@@ -2360,9 +2361,7 @@ netlbl_secattr_to_sid_return_cleanup:
  * assign to the packet.  Returns zero on success, negative values on failure.
  *
  */
-static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
-					u32 base_sid,
-					u32 *sid)
+int selinux_netlbl_skb_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
 {
 	int rc;
 	struct netlbl_lsm_secattr secattr;
@@ -2459,7 +2458,6 @@ void selinux_netlbl_sk_security_init(str
 void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec,
 				      struct sk_security_struct *newssec)
 {
-	newssec->sclass = ssec->sclass;
 	if (ssec->nlbl_state != NLBL_UNSET)
 		newssec->nlbl_state = NLBL_REQUIRE;
 	else
@@ -2481,11 +2479,8 @@ int selinux_netlbl_socket_post_create(st
 				      int sock_family,
 				      u32 sid)
 {
-	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
 	struct sk_security_struct *sksec = sock->sk->sk_security;
 
-	sksec->sclass = isec->sclass;
-
 	if (sock_family != PF_INET)
 		return 0;
 
@@ -2505,24 +2500,23 @@ int selinux_netlbl_socket_post_create(st
  */
 void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
 {
-	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
 	struct sk_security_struct *sksec = sk->sk_security;
 	struct netlbl_lsm_secattr secattr;
 	u32 nlbl_peer_sid;
 
-	sksec->sclass = isec->sclass;
-
 	if (sk->sk_family != PF_INET)
 		return;
 
-	netlbl_secattr_init(&secattr);
-	if (netlbl_sock_getattr(sk, &secattr) == 0 &&
-	    selinux_netlbl_secattr_to_sid(NULL,
-					  &secattr,
-					  sksec->sid,
-					  &nlbl_peer_sid) == 0)
-		sksec->peer_sid = nlbl_peer_sid;
-	netlbl_secattr_destroy(&secattr);
+	if (selinux_compat_net) {
+		netlbl_secattr_init(&secattr);
+		if (netlbl_sock_getattr(sk, &secattr) == 0 &&
+		    selinux_netlbl_secattr_to_sid(NULL,
+						  &secattr,
+						  SECINITSID_UNLABELED,
+						  &nlbl_peer_sid) == 0)
+			sksec->peer_sid = nlbl_peer_sid;
+		netlbl_secattr_destroy(&secattr);
+	}
 
 	sksec->nlbl_state = NLBL_REQUIRE;
 
@@ -2533,32 +2527,6 @@ void selinux_netlbl_sock_graft(struct so
 }
 
 /**
- * selinux_netlbl_inet_conn_request - Handle a new connection request
- * @skb: the packet
- * @sock_sid: the SID of the parent socket
- *
- * Description:
- * If present, use the security attributes of the packet in @skb and the
- * parent sock's SID to arrive at a SID for the new child sock.  Returns the
- * SID of the connection or SECSID_NULL on failure.
- *
- */
-u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
-{
-	int rc;
-	u32 peer_sid;
-
-	rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
-	if (rc != 0)
-		return SECSID_NULL;
-
-	if (peer_sid == SECINITSID_UNLABELED)
-		return SECSID_NULL;
-
-	return peer_sid;
-}
-
-/**
  * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled
  * @inode: the file descriptor's inode
  * @mask: the permission mask
@@ -2598,7 +2566,8 @@ int selinux_netlbl_inode_permission(stru
 
 /**
  * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
- * @sksec: the sock's sk_security_struct
+ * @sock_sid: the socket's SID
+ * @sock_class: the socket's class
  * @skb: the packet
  * @ad: the audit data
  *
@@ -2608,7 +2577,8 @@ int selinux_netlbl_inode_permission(stru
  * error.
  *
  */
-int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
+int selinux_netlbl_sock_rcv_skb(u32 sock_sid,
+				u16 sock_class,
 				struct sk_buff *skb,
 				struct avc_audit_data *ad)
 {
@@ -2616,14 +2586,14 @@ int selinux_netlbl_sock_rcv_skb(struct s
 	u32 netlbl_sid;
 	u32 recv_perm;
 
-	rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid);
+	rc = selinux_netlbl_skb_sid(skb, SECINITSID_UNLABELED, &netlbl_sid);
 	if (rc != 0)
 		return rc;
 
-	if (netlbl_sid == SECINITSID_UNLABELED)
+	if (netlbl_sid == SECSID_NULL)
 		return 0;
 
-	switch (sksec->sclass) {
+	switch (sock_class) {
 	case SECCLASS_UDP_SOCKET:
 		recv_perm = UDP_SOCKET__RECVFROM;
 		break;
@@ -2634,61 +2604,15 @@ int selinux_netlbl_sock_rcv_skb(struct s
 		recv_perm = RAWIP_SOCKET__RECVFROM;
 	}
 
-	rc = avc_has_perm(sksec->sid,
+	rc = avc_has_perm(sock_sid,
 			  netlbl_sid,
-			  sksec->sclass,
+			  sock_class,
 			  recv_perm,
 			  ad);
 	if (rc == 0)
 		return 0;
 
-	netlbl_skbuff_err(skb, rc);
+	netlbl_skbuff_err(skb, rc, 0);
 	return rc;
 }
-
-/**
- * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID
- * @sock: the socket
- *
- * Description:
- * Examine @sock to find the connected peer's SID.  Returns the SID on success
- * or SECSID_NULL on error.
- *
- */
-u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
-{
-	struct sk_security_struct *sksec = sock->sk->sk_security;
-
-	if (sksec->peer_sid == SECINITSID_UNLABELED)
-		return SECSID_NULL;
-
-	return sksec->peer_sid;
-}
-
-/**
- * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
- * @skb: the packet
- *
- * Description:
- * Examine @skb to find the SID assigned to it by NetLabel.  Returns the SID on
- * success, SECSID_NULL on error.
- *
- */
-u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
-{
-	int peer_sid;
-	struct sock *sk = skb->sk;
-	struct inode_security_struct *isec;
-
-	if (sk == NULL || sk->sk_socket == NULL)
-		return SECSID_NULL;
-
-	isec = SOCK_INODE(sk->sk_socket)->i_security;
-	if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0)
-		return SECSID_NULL;
-	if (peer_sid == SECINITSID_UNLABELED)
-		return SECSID_NULL;
-
-	return peer_sid;
-}
 #endif /* CONFIG_NETLABEL */

--
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!)
  2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
                   ` (10 preceding siblings ...)
  2006-10-09 19:42 ` [PATCH 11/11] secid reconciliation: support for NetLabel paul.moore
@ 2006-10-09 20:19 ` James Morris
  2006-10-09 20:30   ` Paul Moore
  2006-10-11 19:20   ` Venkat Yekkirala
  11 siblings, 2 replies; 17+ messages in thread
From: James Morris @ 2006-10-09 20:19 UTC (permalink / raw)
  To: Paul Moore, David S. Miller
  Cc: netdev, selinux, Venkat Yekkirala, Stephen Smalley, Eric Paris

On Mon, 9 Oct 2006, paul.moore@hp.com wrote:

> Please consider this for inclusion into 2.6.20.  If it's too soon to be
> thinking of 2.6.20 let me know and I'll rebase/resend this patchset once I see
> notice of David's net-2.6.20 git tree.

>From an initial review of this patchset, it doesn't look quite ready to 
queue for 2.6.20 (which I plan to to via git once it is).

Outstanding items include resolving the igmp skb hook issue generally, 
testing to verify both the design and implementation, and ensuring that 
all the related policy changes are merged upstream first.



- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!)
  2006-10-09 20:19 ` [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) James Morris
@ 2006-10-09 20:30   ` Paul Moore
  2006-10-09 20:36     ` James Morris
  2006-10-11 19:20   ` Venkat Yekkirala
  1 sibling, 1 reply; 17+ messages in thread
From: Paul Moore @ 2006-10-09 20:30 UTC (permalink / raw)
  To: James Morris
  Cc: David S. Miller, netdev, selinux, Venkat Yekkirala,
	Stephen Smalley, Eric Paris

James Morris wrote:
> On Mon, 9 Oct 2006, paul.moore@hp.com wrote:
> 
>>Please consider this for inclusion into 2.6.20.  If it's too soon to be
>>thinking of 2.6.20 let me know and I'll rebase/resend this patchset once I see
>>notice of David's net-2.6.20 git tree.
> 
> From an initial review of this patchset, it doesn't look quite ready to 
> queue for 2.6.20 (which I plan to to via git once it is).
> 
> Outstanding items include resolving the igmp skb hook issue generally, 
> testing to verify both the design and implementation, and ensuring that 
> all the related policy changes are merged upstream first.

I'll keep the patchset up to date and keep tracking the secid patches (I know
there has been discussion around the IGMP hook this morning).  Once everything
looks okay I'll resend the patchset (with any updates/corrections/etc.) again.

-- 
paul moore
linux security @ hp

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!)
  2006-10-09 20:30   ` Paul Moore
@ 2006-10-09 20:36     ` James Morris
  0 siblings, 0 replies; 17+ messages in thread
From: James Morris @ 2006-10-09 20:36 UTC (permalink / raw)
  To: Paul Moore
  Cc: David S. Miller, netdev, selinux, Venkat Yekkirala,
	Stephen Smalley, Eric Paris

On Mon, 9 Oct 2006, Paul Moore wrote:

> I'll keep the patchset up to date and keep tracking the secid patches (I know
> there has been discussion around the IGMP hook this morning).  Once everything
> looks okay I'll resend the patchset (with any updates/corrections/etc.) again.

Thanks.  I think we're pretty close to finalizing this now, and once 
merged, we can focus on making it useful to normal people :-)


- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!)
  2006-10-09 20:19 ` [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) James Morris
  2006-10-09 20:30   ` Paul Moore
@ 2006-10-11 19:20   ` Venkat Yekkirala
  2006-10-12  7:26     ` James Morris
  1 sibling, 1 reply; 17+ messages in thread
From: Venkat Yekkirala @ 2006-10-11 19:20 UTC (permalink / raw)
  To: 'James Morris', Paul Moore, David S. Miller
  Cc: netdev, selinux, Venkat Yekkirala, Stephen Smalley, Eric Paris

> From an initial review of this patchset, it doesn't look 
> quite ready to 
> queue for 2.6.20 (which I plan to to via git once it is).
> 
> Outstanding items include resolving the igmp skb hook issue 
> generally, 
> testing to verify both the design and implementation, and 
> ensuring that 
> all the related policy changes are merged upstream first.
> 
Regarding the igmp hook issue, we could do a generic hook
like Paul suggested. Would that be more palatable you think?

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!)
  2006-10-11 19:20   ` Venkat Yekkirala
@ 2006-10-12  7:26     ` James Morris
  0 siblings, 0 replies; 17+ messages in thread
From: James Morris @ 2006-10-12  7:26 UTC (permalink / raw)
  To: Venkat Yekkirala
  Cc: Paul Moore, David S. Miller, netdev, selinux, Venkat Yekkirala,
	Stephen Smalley, Eric Paris

On Wed, 11 Oct 2006, Venkat Yekkirala wrote:

> > Outstanding items include resolving the igmp skb hook issue 
> > generally, 
> > testing to verify both the design and implementation, and 
> > ensuring that 
> > all the related policy changes are merged upstream first.
> > 
> Regarding the igmp hook issue, we could do a generic hook
> like Paul suggested. Would that be more palatable you think?

It needs to be investigated to see if anything else in the kernel is doing 
the same thing, and then most likely, a generic hook for 
classifying non-socket packets (you could pass the protocol as a hook 
parameter).


-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2006-10-12  7:26 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-09 19:42 [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) paul.moore
2006-10-09 19:42 ` [PATCH 01/11] secid reconciliation: new SELinux flask definitions paul.moore
2006-10-09 19:42 ` [PATCH 02/11] secid reconciliation: Add LSM hooks paul.moore
2006-10-09 19:42 ` [PATCH 03/11] secid reconciliation: Invoke LSM hook for inbound traffic paul.moore
2006-10-09 19:42 ` [PATCH 04/11] secid reconciliation: Invoke LSM hook for outbound traffic paul.moore
2006-10-09 19:42 ` [PATCH 05/11] secid reconciliation: Label locally generated IPv6 traffic paul.moore
2006-10-09 19:42 ` [PATCH 06/11] secid reconciliation: Label locally generated IPv4 traffic paul.moore
2006-10-09 19:42 ` [PATCH 07/11] secid reconciliation: Enforcement for SELinux paul.moore
2006-10-09 19:42 ` [PATCH 08/11] secid reconciliation: Use secmark when classifying flow using skb paul.moore
2006-10-09 19:42 ` [PATCH 09/11] secid reconciliation: Track peersecid at connection establishment paul.moore
2006-10-09 19:42 ` [PATCH 10/11] secid reconciliation: various fixes paul.moore
2006-10-09 19:42 ` [PATCH 11/11] secid reconciliation: support for NetLabel paul.moore
2006-10-09 20:19 ` [PATCH 00/11] The _entire_ secid reconciliation patchset (tada!) James Morris
2006-10-09 20:30   ` Paul Moore
2006-10-09 20:36     ` James Morris
2006-10-11 19:20   ` Venkat Yekkirala
2006-10-12  7:26     ` James Morris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).