Netdev List
 help / color / mirror / Atom feed
* [patch 03/17] eliminate unused /proc/sys/net/ethernet
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jes, jeff


From: Jes Sorensen <jes@sgi.com>

The /proc/sys/net/ethernet directory has been sitting empty for more than
10 years!  Time to eliminate it!

Signed-off-by: Jes Sorensen <jes@sgi.com>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 net/ethernet/Makefile           |    1 -
 net/ethernet/sysctl_net_ether.c |   14 --------------
 net/sysctl_net.c                |    8 --------
 3 files changed, 23 deletions(-)

diff -puN net/ethernet/Makefile~eliminate-unused-proc-sys-net-ethernet net/ethernet/Makefile
--- devel/net/ethernet/Makefile~eliminate-unused-proc-sys-net-ethernet	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/net/ethernet/Makefile	2006-06-01 20:31:49.000000000 -0700
@@ -3,6 +3,5 @@
 #
 
 obj-y					+= eth.o
-obj-$(CONFIG_SYSCTL)			+= sysctl_net_ether.o
 obj-$(subst m,y,$(CONFIG_IPX))		+= pe2.o
 obj-$(subst m,y,$(CONFIG_ATALK))	+= pe2.o
diff -L net/ethernet/sysctl_net_ether.c -puN net/ethernet/sysctl_net_ether.c~eliminate-unused-proc-sys-net-ethernet /dev/null
--- devel/net/ethernet/sysctl_net_ether.c
+++ /dev/null	2006-06-01 17:04:03.273681250 -0700
@@ -1,14 +0,0 @@
-/* -*- linux-c -*-
- * sysctl_net_ether.c: sysctl interface to net Ethernet subsystem.
- *
- * Begun April 1, 1996, Mike Shaver.
- * Added /proc/sys/net/ether directory entry (empty =) ). [MS]
- */
-
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/if_ether.h>
-
-ctl_table ether_table[] = {
-	{0}
-};
diff -puN net/sysctl_net.c~eliminate-unused-proc-sys-net-ethernet net/sysctl_net.c
--- devel/net/sysctl_net.c~eliminate-unused-proc-sys-net-ethernet	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/net/sysctl_net.c	2006-06-01 20:31:49.000000000 -0700
@@ -37,14 +37,6 @@ struct ctl_table net_table[] = {
 		.mode		= 0555,
 		.child		= core_table,
 	},
-#ifdef CONFIG_NET
-	{
-		.ctl_name	= NET_ETHER,
-		.procname	= "ethernet",
-		.mode		= 0555,
-		.child		= ether_table,
-	},
-#endif
 #ifdef CONFIG_INET
 	{
 		.ctl_name	= NET_IPV4,
_

^ permalink raw reply

* [patch 04/17] ppp_async hang fix
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, xeb, paulus


From: <xeb@mail.ru>

Adapted from  http://bugzilla.kernel.org/show_bug.cgi?id=6530

Reschedule the async Tx tasklet if the transmit queue was full.

Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/net/ppp_async.c |    2 ++
 1 file changed, 2 insertions(+)

diff -puN drivers/net/ppp_async.c~ppp_async-hang-fix drivers/net/ppp_async.c
--- devel/drivers/net/ppp_async.c~ppp_async-hang-fix	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/drivers/net/ppp_async.c	2006-06-01 20:31:49.000000000 -0700
@@ -516,6 +516,8 @@ static void ppp_async_process(unsigned l
 	/* try to push more stuff out */
 	if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_async_push(ap))
 		ppp_output_wakeup(&ap->chan);
+	else if (test_bit(XMIT_FULL, &ap->xmit_flags))
+		ppp_asynctty_wakeup(ap->tty);
 }
 
 /*
_

^ permalink raw reply

* [patch 07/17] secmark: Add new flask definitions to SELinux
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jmorris


From: James Morris <jmorris@namei.org>

Secmark implements a new scheme for adding security markings to packets via
iptables, as well as changes to SELinux to use these markings for security
policy enforcement.  The rationale for this scheme is explained and discussed
in detail in the original threads: 

 http://thread.gmane.org/gmane.linux.network/34927/ 
 http://thread.gmane.org/gmane.linux.network/35244/

Examples of policy and rulesets, as well as a full archive of patches for
iptables and SELinux userland, may be found at:
http://people.redhat.com/jmorris/selinux/secmark/

The code has been tested with various compilation options and in several
scenarios, including with 'complicated' protocols such as FTP and also with
the new generic conntrack code with IPv6 connection tracking.



This patch:

Add support for a new object class ('packet'), and associated permissions
('send', 'recv', 'relabelto').  These are used to enforce security policy for
network packets labeled with SECMARK, and for adding labeling rules.

Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 security/selinux/include/av_perm_to_string.h |    3 +++
 security/selinux/include/av_permissions.h    |    3 +++
 security/selinux/include/class_to_string.h   |    1 +
 security/selinux/include/flask.h             |    1 +
 4 files changed, 8 insertions(+)

diff -puN security/selinux/include/av_permissions.h~secmark-add-new-flask-definitions-to-selinux security/selinux/include/av_permissions.h
--- devel/security/selinux/include/av_permissions.h~secmark-add-new-flask-definitions-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/include/av_permissions.h	2006-06-01 20:31:50.000000000 -0700
@@ -956,3 +956,6 @@
 #define APPLETALK_SOCKET__SEND_MSG                0x00100000UL
 #define APPLETALK_SOCKET__NAME_BIND               0x00200000UL
 
+#define PACKET__SEND                              0x00000001UL
+#define PACKET__RECV                              0x00000002UL
+#define PACKET__RELABELTO                         0x00000004UL
diff -puN security/selinux/include/av_perm_to_string.h~secmark-add-new-flask-definitions-to-selinux security/selinux/include/av_perm_to_string.h
--- devel/security/selinux/include/av_perm_to_string.h~secmark-add-new-flask-definitions-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/include/av_perm_to_string.h	2006-06-01 20:31:50.000000000 -0700
@@ -239,3 +239,6 @@
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
+   S_(SECCLASS_PACKET, PACKET__SEND, "send")
+   S_(SECCLASS_PACKET, PACKET__RECV, "recv")
+   S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
diff -puN security/selinux/include/class_to_string.h~secmark-add-new-flask-definitions-to-selinux security/selinux/include/class_to_string.h
--- devel/security/selinux/include/class_to_string.h~secmark-add-new-flask-definitions-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/include/class_to_string.h	2006-06-01 20:31:50.000000000 -0700
@@ -59,3 +59,4 @@
     S_("association")
     S_("netlink_kobject_uevent_socket")
     S_("appletalk_socket")
+    S_("packet")
diff -puN security/selinux/include/flask.h~secmark-add-new-flask-definitions-to-selinux security/selinux/include/flask.h
--- devel/security/selinux/include/flask.h~secmark-add-new-flask-definitions-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/include/flask.h	2006-06-01 20:31:50.000000000 -0700
@@ -61,6 +61,7 @@
 #define SECCLASS_ASSOCIATION                             54
 #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET           55
 #define SECCLASS_APPLETALK_SOCKET                        56
+#define SECCLASS_PACKET                                  57
 
 /*
  * Security identifier indices for initial entities
_

^ permalink raw reply

* [patch 08/17] secmark: Add SELinux exports
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jmorris


From: James Morris <jmorris@namei.org>

Add and export new functions to the in-kernel SELinux API in support of the
new secmark-based packet controls.

Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 include/linux/selinux.h    |   32 ++++++++++++++++++++++++++++++++
 security/selinux/exports.c |   22 ++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff -puN include/linux/selinux.h~secmark-add-selinux-exports include/linux/selinux.h
--- devel/include/linux/selinux.h~secmark-add-selinux-exports	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/linux/selinux.h	2006-06-01 20:31:50.000000000 -0700
@@ -118,6 +118,27 @@ void selinux_get_ipc_sid(const struct ke
  */
 void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
 
+/**
+ *     selinux_string_to_sid - map a security context string to a security ID
+ *     @str: the security context string to be mapped
+ *     @sid: ID value returned via this.
+ *
+ *     Returns 0 if successful, with the SID stored in sid.  A value
+ *     of zero for sid indicates no SID could be determined (but no error
+ *     occurred).
+ */
+int selinux_string_to_sid(char *str, u32 *sid);
+
+/**
+ *     selinux_relabel_packet_permission - check permission to relabel a packet
+ *     @sid: ID value to be applied to network packet (via SECMARK, most likely)
+ *
+ *     Returns 0 if the current task is allowed to label packets with the
+ *     supplied security ID.  Note that it is implicit that the packet is always
+ *     being relabeled from the default unlabled value, and that the access
+ *     control decision is made in the AVC.
+ */
+int selinux_relabel_packet_permission(u32 sid);
 
 #else
 
@@ -172,6 +193,17 @@ static inline void selinux_get_task_sid(
 	*sid = 0;
 }
 
+static inline int selinux_string_to_sid(const char *str, u32 *sid)
+{
+       *sid = 0;
+       return 0;
+}
+
+static inline int selinux_relabel_packet_permission(u32 sid)
+{
+	return 0;
+}
+
 #endif	/* CONFIG_SECURITY_SELINUX */
 
 #endif /* _LINUX_SELINUX_H */
diff -puN security/selinux/exports.c~secmark-add-selinux-exports security/selinux/exports.c
--- devel/security/selinux/exports.c~secmark-add-selinux-exports	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/exports.c	2006-06-01 20:31:50.000000000 -0700
@@ -72,3 +72,25 @@ void selinux_get_task_sid(struct task_st
 	*sid = 0;
 }
 
+int selinux_string_to_sid(char *str, u32 *sid)
+{
+	if (selinux_enabled)
+		return security_context_to_sid(str, strlen(str), sid);
+	else {
+		*sid = 0;
+		return 0;
+	}
+}
+EXPORT_SYMBOL_GPL(selinux_string_to_sid);
+
+int selinux_relabel_packet_permission(u32 sid)
+{
+	if (selinux_enabled) {
+		struct task_security_struct *tsec = current->security;
+
+		return avc_has_perm(tsec->sid, sid, SECCLASS_PACKET,
+				    PACKET__RELABELTO, NULL);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission);
_

^ permalink raw reply

* [patch 09/17] secmark: Add secmark support to core networking.
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jmorris


From: James Morris <jmorris@namei.org>

Add a secmark field to the skbuff structure, to allow security subsystems to
place security markings on network packets.  This is similar to the nfmark
field, except is intended for implementing security policy, rather than than
networking policy.

This patch was already acked in principle by Dave Miller.

Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 include/linux/skbuff.h          |   22 ++++++++++++++++++++++
 net/Kconfig                     |    7 +++++++
 net/core/skbuff.c               |    3 ++-
 net/ipv4/ip_output.c            |    1 +
 net/ipv4/netfilter/ipt_REJECT.c |    1 +
 net/ipv6/ip6_output.c           |    1 +
 6 files changed, 34 insertions(+), 1 deletion(-)

diff -puN include/linux/skbuff.h~secmark-add-secmark-support-to-core-networking include/linux/skbuff.h
--- devel/include/linux/skbuff.h~secmark-add-secmark-support-to-core-networking	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/linux/skbuff.h	2006-06-01 20:31:50.000000000 -0700
@@ -209,6 +209,7 @@ enum {
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@tc_index: Traffic control index
  *	@tc_verd: traffic control verdict
+ *	@secmark: security marking
  */
 
 struct sk_buff {
@@ -288,6 +289,9 @@ struct sk_buff {
 #ifdef CONFIG_NET_DMA
 	dma_cookie_t		dma_cookie;
 #endif
+#ifdef CONFIG_NETWORK_SECMARK
+	__u32			secmark;
+#endif
 
 
 	/* These elements must be at the end, see alloc_skb() for details.  */
@@ -1399,5 +1403,23 @@ static inline void nf_reset(struct sk_bu
 static inline void nf_reset(struct sk_buff *skb) {}
 #endif /* CONFIG_NETFILTER */
 
+#ifdef CONFIG_NETWORK_SECMARK
+static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
+{
+	to->secmark = from->secmark;
+}
+
+static inline void skb_init_secmark(struct sk_buff *skb)
+{
+	skb->secmark = 0;
+}
+#else
+static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
+{ }
+
+static inline void skb_init_secmark(struct sk_buff *skb)
+{ }
+#endif
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff -puN net/core/skbuff.c~secmark-add-secmark-support-to-core-networking net/core/skbuff.c
--- devel/net/core/skbuff.c~secmark-add-secmark-support-to-core-networking	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/core/skbuff.c	2006-06-01 20:31:50.000000000 -0700
@@ -464,7 +464,7 @@ struct sk_buff *skb_clone(struct sk_buff
 	n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
 	C(input_dev);
 #endif
-
+	skb_copy_secmark(n, skb);
 #endif
 	C(truesize);
 	atomic_set(&n->users, 1);
@@ -526,6 +526,7 @@ static void copy_skb_header(struct sk_bu
 #endif
 	new->tc_index	= old->tc_index;
 #endif
+	skb_copy_secmark(new, old);
 	atomic_set(&new->users, 1);
 	skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size;
 	skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs;
diff -puN net/ipv4/ip_output.c~secmark-add-secmark-support-to-core-networking net/ipv4/ip_output.c
--- devel/net/ipv4/ip_output.c~secmark-add-secmark-support-to-core-networking	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/ip_output.c	2006-06-01 20:31:50.000000000 -0700
@@ -410,6 +410,7 @@ static void ip_copy_metadata(struct sk_b
 	nf_bridge_get(to->nf_bridge);
 #endif
 #endif
+	skb_copy_secmark(to, from);
 }
 
 /*
diff -puN net/ipv4/netfilter/ipt_REJECT.c~secmark-add-secmark-support-to-core-networking net/ipv4/netfilter/ipt_REJECT.c
--- devel/net/ipv4/netfilter/ipt_REJECT.c~secmark-add-secmark-support-to-core-networking	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ipt_REJECT.c	2006-06-01 20:31:50.000000000 -0700
@@ -147,6 +147,7 @@ static void send_reset(struct sk_buff *o
 	/* This packet will not be the same as the other: clear nf fields */
 	nf_reset(nskb);
 	nskb->nfmark = 0;
+	skb_init_secmark(nskb);
 
 	tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
 
diff -puN net/ipv6/ip6_output.c~secmark-add-secmark-support-to-core-networking net/ipv6/ip6_output.c
--- devel/net/ipv6/ip6_output.c~secmark-add-secmark-support-to-core-networking	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv6/ip6_output.c	2006-06-01 20:31:50.000000000 -0700
@@ -459,6 +459,7 @@ static void ip6_copy_metadata(struct sk_
 	nf_bridge_get(to->nf_bridge);
 #endif
 #endif
+	skb_copy_secmark(to, from);
 }
 
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
diff -puN net/Kconfig~secmark-add-secmark-support-to-core-networking net/Kconfig
--- devel/net/Kconfig~secmark-add-secmark-support-to-core-networking	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/Kconfig	2006-06-01 20:31:50.000000000 -0700
@@ -66,6 +66,13 @@ source "net/ipv6/Kconfig"
 
 endif # if INET
 
+config NETWORK_SECMARK
+	bool "Security Marking"
+	help
+	  This enables security marking of network packets, similar
+	  to nfmark, but designated for security purposes.
+	  If you are unsure how to answer this question, answer N.
+
 menuconfig NETFILTER
 	bool "Network packet filtering (replaces ipchains)"
 	---help---
_

^ permalink raw reply

* [patch 10/17] secmark: Add xtables SECMARK target
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jmorris


From: James Morris <jmorris@namei.org>

Add a SECMARK target to xtables, allowing the admin to apply security marks to
packets via both iptables and ip6tables.

The target currently handles SELinux security marking, but can be extended
for other purposes as needed.

Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 include/linux/netfilter/xt_SECMARK.h |   26 ++++
 net/netfilter/Kconfig                |    9 +
 net/netfilter/Makefile               |    1 
 net/netfilter/xt_SECMARK.c           |  156 +++++++++++++++++++++++++
 4 files changed, 192 insertions(+)

diff -puN /dev/null include/linux/netfilter/xt_SECMARK.h
--- /dev/null	2006-06-01 17:04:03.273681250 -0700
+++ devel-akpm/include/linux/netfilter/xt_SECMARK.h	2006-06-01 20:31:50.000000000 -0700
@@ -0,0 +1,26 @@
+#ifndef _XT_SECMARK_H_target
+#define _XT_SECMARK_H_target
+
+/*
+ * This is intended for use by various security subsystems (but not
+ * at the same time).
+ *
+ * 'mode' refers to the specific security subsystem which the
+ * packets are being marked for.
+ */
+#define SECMARK_MODE_SEL	0x01		/* SELinux */
+#define SECMARK_SELCTX_MAX	256
+
+struct xt_secmark_target_selinux_info {
+	u_int32_t selsid;
+	char selctx[SECMARK_SELCTX_MAX];
+};
+
+struct xt_secmark_target_info {
+	u_int8_t mode;
+	union {
+		struct xt_secmark_target_selinux_info sel;
+	} u;
+};
+
+#endif /*_XT_SECMARK_H_target */
diff -puN net/netfilter/Kconfig~secmark-add-xtables-secmark-target net/netfilter/Kconfig
--- devel/net/netfilter/Kconfig~secmark-add-xtables-secmark-target	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/Kconfig	2006-06-01 20:31:50.000000000 -0700
@@ -174,6 +174,15 @@ config NETFILTER_XT_TARGET_NOTRACK
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_SECMARK
+	tristate '"SECMARK" target support'
+	depends on NETFILTER_XTABLES && NETWORK_SECMARK
+	help
+	  The SECMARK target allows security marking of network
+	  packets, for use with security subsystems.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_COMMENT
 	tristate  '"comment" match support'
 	depends on NETFILTER_XTABLES
diff -puN net/netfilter/Makefile~secmark-add-xtables-secmark-target net/netfilter/Makefile
--- devel/net/netfilter/Makefile~secmark-add-xtables-secmark-target	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/Makefile	2006-06-01 20:31:50.000000000 -0700
@@ -28,6 +28,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMAR
 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
 
 # matches
 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
diff -puN /dev/null net/netfilter/xt_SECMARK.c
--- /dev/null	2006-06-01 17:04:03.273681250 -0700
+++ devel-akpm/net/netfilter/xt_SECMARK.c	2006-06-01 20:31:50.000000000 -0700
@@ -0,0 +1,156 @@
+/*
+ * Module for modifying the secmark field of the skb, for use by
+ * security subsystems.
+ *
+ * Based on the nfmark match by:
+ * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/selinux.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_SECMARK.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables SECMARK modification module");
+MODULE_ALIAS("ipt_SECMARK");
+MODULE_ALIAS("ip6t_SECMARK");
+
+#define PFX "SECMARK: "
+
+static u8 mode;
+
+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,
+			   const void *targinfo, void *userinfo)
+{
+	u32 secmark = 0;
+	const struct xt_secmark_target_info *info = targinfo;
+
+	BUG_ON(info->mode != mode);
+
+	switch (mode) {
+	case SECMARK_MODE_SEL:
+		secmark = info->u.sel.selsid;
+		break;
+
+	default:
+		BUG();
+	}
+
+	if ((*pskb)->secmark != secmark)
+		(*pskb)->secmark = secmark;
+
+	return XT_CONTINUE;
+}
+
+static int checkentry_selinux(struct xt_secmark_target_info *info)
+{
+	int err;
+	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
+
+	err = selinux_string_to_sid(sel->selctx, &sel->selsid);
+	if (err) {
+		if (err == -EINVAL)
+			printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
+			       sel->selctx);
+		return 0;
+	}
+
+	if (!sel->selsid) {
+		printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
+		       sel->selctx);
+		return 0;
+	}
+
+	err = selinux_relabel_packet_permission(sel->selsid);
+	if (err) {
+		printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+		      const struct xt_target *target, void *targinfo,
+		      unsigned int targinfosize, unsigned int hook_mask)
+{
+	struct xt_secmark_target_info *info = targinfo;
+
+	if (mode && mode != info->mode) {
+		printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
+		       "rules for mode %hu\n", mode, info->mode);
+		return 0;
+	}
+
+	switch (info->mode) {
+	case SECMARK_MODE_SEL:
+		if (!checkentry_selinux(info))
+			return 0;
+		break;
+
+	default:
+		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+		return 0;
+	}
+
+	if (!mode)
+		mode = info->mode;
+	return 1;
+}
+
+static struct xt_target ipt_secmark_reg = {
+	.name		= "SECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_secmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET,
+	.revision	= 0,
+};
+
+static struct xt_target ip6t_secmark_reg = {
+	.name		= "SECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_secmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET6,
+	.revision	= 0,
+};
+
+static int __init xt_secmark_init(void)
+{
+	int err;
+
+	err = xt_register_target(&ipt_secmark_reg);
+	if (err)
+		return err;
+
+	err = xt_register_target(&ip6t_secmark_reg);
+	if (err)
+		xt_unregister_target(&ipt_secmark_reg);
+
+	return err;
+}
+
+static void __exit xt_secmark_fini(void)
+{
+	xt_unregister_target(&ip6t_secmark_reg);
+	xt_unregister_target(&ipt_secmark_reg);
+}
+
+module_init(xt_secmark_init);
+module_exit(xt_secmark_fini);
_

^ permalink raw reply

* [patch 12/17] secmark: Add CONNSECMARK xtables target
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jmorris


From: James Morris <jmorris@namei.org>

Add a new xtables target, CONNSECMARK, which is used to specify rules for
copying security marks from packets to connections, and for copyying security
marks back from connections to packets.  This is similar to the CONNMARK
target, but is more limited in scope in that it only allows copying of
security marks to and from packets, as this is all it needs to do.

A typical scenario would be to apply a security mark to a 'new' packet with
SECMARK, then copy that to its conntrack via CONNMARK, and then restore the
security mark from the connection to established and related packets on that
connection.

Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 include/linux/netfilter/xt_CONNSECMARK.h |   13 +
 net/netfilter/Kconfig                    |   11 +
 net/netfilter/Makefile                   |    1 
 net/netfilter/xt_CONNSECMARK.c           |  155 +++++++++++++++++++++
 4 files changed, 180 insertions(+)

diff -puN /dev/null include/linux/netfilter/xt_CONNSECMARK.h
--- /dev/null	2006-06-01 17:04:03.273681250 -0700
+++ devel-akpm/include/linux/netfilter/xt_CONNSECMARK.h	2006-06-01 20:31:50.000000000 -0700
@@ -0,0 +1,13 @@
+#ifndef _XT_CONNSECMARK_H_target
+#define _XT_CONNSECMARK_H_target
+
+enum {
+	CONNSECMARK_SAVE = 1,
+	CONNSECMARK_RESTORE,
+};
+
+struct xt_connsecmark_target_info {
+	u_int8_t mode;
+};
+
+#endif /*_XT_CONNSECMARK_H_target */
diff -puN net/netfilter/Kconfig~secmark-add-connsecmark-xtables-target net/netfilter/Kconfig
--- devel/net/netfilter/Kconfig~secmark-add-connsecmark-xtables-target	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/Kconfig	2006-06-01 20:31:50.000000000 -0700
@@ -195,6 +195,17 @@ config NETFILTER_XT_TARGET_SECMARK
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_TARGET_CONNSECMARK
+	tristate '"CONNSECMARK" target support'
+	depends on NETFILTER_XTABLES && (NF_CONNTRACK_SECMARK || IP_NF_CONNTRACK_SECMARK)
+	help
+	  The CONNSECMARK target copies security markings from packets
+	  to connections, and restores security markings from connections
+	  to packets (if the packets are not already marked).  This would
+	  normally be used in conjunction with the SECMARK target.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_COMMENT
 	tristate  '"comment" match support'
 	depends on NETFILTER_XTABLES
diff -puN net/netfilter/Makefile~secmark-add-connsecmark-xtables-target net/netfilter/Makefile
--- devel/net/netfilter/Makefile~secmark-add-connsecmark-xtables-target	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/Makefile	2006-06-01 20:31:50.000000000 -0700
@@ -29,6 +29,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) +
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
 
 # matches
 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
diff -puN /dev/null net/netfilter/xt_CONNSECMARK.c
--- /dev/null	2006-06-01 17:04:03.273681250 -0700
+++ devel-akpm/net/netfilter/xt_CONNSECMARK.c	2006-06-01 20:31:50.000000000 -0700
@@ -0,0 +1,155 @@
+/*
+ * This module is used to copy security markings from packets
+ * to connections, and restore security markings from connections
+ * back to packets.  This would normally be performed in conjunction
+ * with the SECMARK target and state match.
+ *
+ * Based somewhat on CONNMARK:
+ *   Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ *    by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CONNSECMARK.h>
+#include <net/netfilter/nf_conntrack_compat.h>
+
+#define PFX "CONNSECMARK: "
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module");
+MODULE_ALIAS("ipt_CONNSECMARK");
+MODULE_ALIAS("ip6t_CONNSECMARK");
+
+/*
+ * 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)
+{
+	if (skb->secmark) {
+		u32 *connsecmark;
+		enum ip_conntrack_info ctinfo;
+
+		connsecmark = nf_ct_get_secmark(skb, &ctinfo);
+		if (connsecmark && !*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.
+ */
+static void secmark_restore(struct sk_buff *skb)
+{
+	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;
+	}
+}
+
+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,
+			   const void *targinfo, void *userinfo)
+{
+	struct sk_buff *skb = *pskb;
+	const struct xt_connsecmark_target_info *info = targinfo;
+
+	switch (info->mode) {
+	case CONNSECMARK_SAVE:
+		secmark_save(skb);
+		break;
+
+	case CONNSECMARK_RESTORE:
+		secmark_restore(skb);
+		break;
+
+	default:
+		BUG();
+	}
+
+	return XT_CONTINUE;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+		      const struct xt_target *target, void *targinfo,
+		      unsigned int targinfosize, unsigned int hook_mask)
+{
+	struct xt_connsecmark_target_info *info = targinfo;
+
+	switch (info->mode) {
+	case CONNSECMARK_SAVE:
+	case CONNSECMARK_RESTORE:
+		break;
+
+	default:
+		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+		return 0;
+	}
+
+	return 1;
+}
+
+static struct xt_target ipt_connsecmark_reg = {
+	.name		= "CONNSECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_connsecmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET,
+	.revision	= 0,
+};
+
+static struct xt_target ip6t_connsecmark_reg = {
+	.name		= "CONNSECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_connsecmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET6,
+	.revision	= 0,
+};
+
+static int __init xt_connsecmark_init(void)
+{
+	int err;
+
+	need_conntrack();
+
+	err = xt_register_target(&ipt_connsecmark_reg);
+	if (err)
+		return err;
+
+	err = xt_register_target(&ip6t_connsecmark_reg);
+	if (err)
+		xt_unregister_target(&ipt_connsecmark_reg);
+
+	return err;
+}
+
+static void __exit xt_connsecmark_fini(void)
+{
+	xt_unregister_target(&ip6t_connsecmark_reg);
+	xt_unregister_target(&ipt_connsecmark_reg);
+}
+
+module_init(xt_connsecmark_init);
+module_exit(xt_connsecmark_fini);
_

^ permalink raw reply

* [patch 11/17] secmark: Add secmark support to conntrack
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jmorris


From: James Morris <jmorris@namei.org>

Add a secmark field to IP and NF conntracks, so that security markings on
packets can be copied to their associated connections, and also copied back to
packets as required.  This is similar to the network mark field currently used
with conntrack, although it is intended for enforcement of security policy
rather than network policy.

Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 include/linux/netfilter_ipv4/ip_conntrack.h  |    4 ++
 include/net/netfilter/nf_conntrack.h         |    4 ++
 include/net/netfilter/nf_conntrack_compat.h  |   26 +++++++++++++++++
 net/ipv4/netfilter/Kconfig                   |   12 +++++++
 net/ipv4/netfilter/ip_conntrack_core.c       |    3 +
 net/ipv4/netfilter/ip_conntrack_standalone.c |    5 +++
 net/netfilter/Kconfig                        |   12 +++++++
 net/netfilter/nf_conntrack_core.c            |    3 +
 net/netfilter/nf_conntrack_standalone.c      |    5 +++
 9 files changed, 74 insertions(+)

diff -puN include/linux/netfilter_ipv4/ip_conntrack.h~secmark-add-secmark-support-to-conntrack include/linux/netfilter_ipv4/ip_conntrack.h
--- devel/include/linux/netfilter_ipv4/ip_conntrack.h~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/linux/netfilter_ipv4/ip_conntrack.h	2006-06-01 20:31:50.000000000 -0700
@@ -120,6 +120,10 @@ struct ip_conntrack
 	u_int32_t mark;
 #endif
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+	u_int32_t secmark;
+#endif
+
 	/* Traversed often, so hopefully in different cacheline to top */
 	/* These are my tuples; original and reply */
 	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
diff -puN include/net/netfilter/nf_conntrack_compat.h~secmark-add-secmark-support-to-conntrack include/net/netfilter/nf_conntrack_compat.h
--- devel/include/net/netfilter/nf_conntrack_compat.h~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/net/netfilter/nf_conntrack_compat.h	2006-06-01 20:31:50.000000000 -0700
@@ -20,6 +20,19 @@ static inline u_int32_t *nf_ct_get_mark(
 }
 #endif /* CONFIG_IP_NF_CONNTRACK_MARK */
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+					   u_int32_t *ctinfo)
+{
+	struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
+
+	if (ct)
+		return &ct->secmark;
+	else
+		return NULL;
+}
+#endif /* CONFIG_IP_NF_CONNTRACK_SECMARK */
+
 #ifdef CONFIG_IP_NF_CT_ACCT
 static inline struct ip_conntrack_counter *
 nf_ct_get_counters(const struct sk_buff *skb)
@@ -70,6 +83,19 @@ static inline u_int32_t *nf_ct_get_mark(
 }
 #endif /* CONFIG_NF_CONNTRACK_MARK */
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+					   u_int32_t *ctinfo)
+{
+	struct nf_conn *ct = nf_ct_get(skb, ctinfo);
+
+	if (ct)
+		return &ct->secmark;
+	else
+		return NULL;
+}
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
 #ifdef CONFIG_NF_CT_ACCT
 static inline struct ip_conntrack_counter *
 nf_ct_get_counters(const struct sk_buff *skb)
diff -puN include/net/netfilter/nf_conntrack.h~secmark-add-secmark-support-to-conntrack include/net/netfilter/nf_conntrack.h
--- devel/include/net/netfilter/nf_conntrack.h~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/include/net/netfilter/nf_conntrack.h	2006-06-01 20:31:50.000000000 -0700
@@ -113,6 +113,10 @@ struct nf_conn
 	u_int32_t mark;
 #endif
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+	u_int32_t secmark;
+#endif
+
 	/* Storage reserved for other modules: */
 	union nf_conntrack_proto proto;
 
diff -puN net/ipv4/netfilter/ip_conntrack_core.c~secmark-add-secmark-support-to-conntrack net/ipv4/netfilter/ip_conntrack_core.c
--- devel/net/ipv4/netfilter/ip_conntrack_core.c~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ip_conntrack_core.c	2006-06-01 20:31:50.000000000 -0700
@@ -724,6 +724,9 @@ init_conntrack(struct ip_conntrack_tuple
 		/* this is ugly, but there is no other place where to put it */
 		conntrack->nat.masq_index = exp->master->nat.masq_index;
 #endif
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+		conntrack->secmark = exp->master->secmark;
+#endif
 		nf_conntrack_get(&conntrack->master->ct_general);
 		CONNTRACK_STAT_INC(expect_new);
 	} else {
diff -puN net/ipv4/netfilter/ip_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack net/ipv4/netfilter/ip_conntrack_standalone.c
--- devel/net/ipv4/netfilter/ip_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ip_conntrack_standalone.c	2006-06-01 20:31:50.000000000 -0700
@@ -189,6 +189,11 @@ static int ct_seq_show(struct seq_file *
 		return -ENOSPC;
 #endif
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+	if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+		return -ENOSPC;
+#endif
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
 		return -ENOSPC;
 
diff -puN net/ipv4/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack net/ipv4/netfilter/Kconfig
--- devel/net/ipv4/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/Kconfig	2006-06-01 20:31:50.000000000 -0700
@@ -55,6 +55,18 @@ config IP_NF_CONNTRACK_MARK
 	  of packets, but this mark value is kept in the conntrack session
 	  instead of the individual packets.
 	
+config IP_NF_CONNTRACK_SECMARK
+	bool  'Connection tracking security mark support'
+	depends on IP_NF_CONNTRACK && NETWORK_SECMARK
+	help
+	  This option enables security markings to be applied to
+	  connections.  Typically they are copied to connections from
+	  packets using the CONNSECMARK target and copied back from
+	  connections to packets with the same target, with the packets
+	  being originally labeled via SECMARK.
+
+	  If unsure, say 'N'.
+
 config IP_NF_CONNTRACK_EVENTS
 	bool "Connection tracking events (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && IP_NF_CONNTRACK
diff -puN net/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack net/netfilter/Kconfig
--- devel/net/netfilter/Kconfig~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/Kconfig	2006-06-01 20:31:50.000000000 -0700
@@ -60,6 +60,18 @@ config NF_CONNTRACK_MARK
 	  of packets, but this mark value is kept in the conntrack session
 	  instead of the individual packets.
 
+config NF_CONNTRACK_SECMARK
+	bool  'Connection tracking security mark support'
+	depends on NF_CONNTRACK && NETWORK_SECMARK
+	help
+	  This option enables security markings to be applied to
+	  connections.  Typically they are copied to connections from
+	  packets using the CONNSECMARK target and copied back from
+	  connections to packets with the same target, with the packets
+	  being originally labeled via SECMARK.
+
+	  If unsure, say 'N'.
+
 config NF_CONNTRACK_EVENTS
 	bool "Connection tracking events (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && NF_CONNTRACK
diff -puN net/netfilter/nf_conntrack_core.c~secmark-add-secmark-support-to-conntrack net/netfilter/nf_conntrack_core.c
--- devel/net/netfilter/nf_conntrack_core.c~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/nf_conntrack_core.c	2006-06-01 20:31:50.000000000 -0700
@@ -990,6 +990,9 @@ init_conntrack(const struct nf_conntrack
 #ifdef CONFIG_NF_CONNTRACK_MARK
 		conntrack->mark = exp->master->mark;
 #endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+		conntrack->secmark = exp->master->secmark;
+#endif
 		nf_conntrack_get(&conntrack->master->ct_general);
 		NF_CT_STAT_INC(expect_new);
 	} else
diff -puN net/netfilter/nf_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack net/netfilter/nf_conntrack_standalone.c
--- devel/net/netfilter/nf_conntrack_standalone.c~secmark-add-secmark-support-to-conntrack	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/netfilter/nf_conntrack_standalone.c	2006-06-01 20:31:50.000000000 -0700
@@ -213,6 +213,11 @@ static int ct_seq_show(struct seq_file *
 		return -ENOSPC;
 #endif
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+	if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+		return -ENOSPC;
+#endif
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
 		return -ENOSPC;
 	
_

^ permalink raw reply

* [patch 05/17] selinux: add security class for appletalk sockets
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, cpebenito, jmorris, sds


From: Christopher J. PeBenito <cpebenito@tresys.com>

Add a security class for appletalk sockets so that they can be
distinguished in SELinux policy.  Please apply.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: James Morris <jmorris@namei.org>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 security/selinux/hooks.c                   |    2 +
 security/selinux/include/av_inherit.h      |    1 
 security/selinux/include/av_permissions.h  |   23 +++++++++++++++++++
 security/selinux/include/class_to_string.h |    1 
 security/selinux/include/flask.h           |    1 
 5 files changed, 28 insertions(+)

diff -puN security/selinux/hooks.c~selinux-add-security-class-for-appletalk-sockets security/selinux/hooks.c
--- devel/security/selinux/hooks.c~selinux-add-security-class-for-appletalk-sockets	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/hooks.c	2006-06-01 20:31:49.000000000 -0700
@@ -696,6 +696,8 @@ static inline u16 socket_type_to_securit
 		return SECCLASS_PACKET_SOCKET;
 	case PF_KEY:
 		return SECCLASS_KEY_SOCKET;
+	case PF_APPLETALK:
+		return SECCLASS_APPLETALK_SOCKET;
 	}
 
 	return SECCLASS_SOCKET;
diff -puN security/selinux/include/av_inherit.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/av_inherit.h
--- devel/security/selinux/include/av_inherit.h~selinux-add-security-class-for-appletalk-sockets	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/av_inherit.h	2006-06-01 20:31:49.000000000 -0700
@@ -29,3 +29,4 @@
    S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL)
    S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
    S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
+   S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
diff -puN security/selinux/include/av_permissions.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/av_permissions.h
--- devel/security/selinux/include/av_permissions.h~selinux-add-security-class-for-appletalk-sockets	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/av_permissions.h	2006-06-01 20:31:49.000000000 -0700
@@ -933,3 +933,26 @@
 #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG   0x00100000UL
 #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND  0x00200000UL
 
+#define APPLETALK_SOCKET__IOCTL                   0x00000001UL
+#define APPLETALK_SOCKET__READ                    0x00000002UL
+#define APPLETALK_SOCKET__WRITE                   0x00000004UL
+#define APPLETALK_SOCKET__CREATE                  0x00000008UL
+#define APPLETALK_SOCKET__GETATTR                 0x00000010UL
+#define APPLETALK_SOCKET__SETATTR                 0x00000020UL
+#define APPLETALK_SOCKET__LOCK                    0x00000040UL
+#define APPLETALK_SOCKET__RELABELFROM             0x00000080UL
+#define APPLETALK_SOCKET__RELABELTO               0x00000100UL
+#define APPLETALK_SOCKET__APPEND                  0x00000200UL
+#define APPLETALK_SOCKET__BIND                    0x00000400UL
+#define APPLETALK_SOCKET__CONNECT                 0x00000800UL
+#define APPLETALK_SOCKET__LISTEN                  0x00001000UL
+#define APPLETALK_SOCKET__ACCEPT                  0x00002000UL
+#define APPLETALK_SOCKET__GETOPT                  0x00004000UL
+#define APPLETALK_SOCKET__SETOPT                  0x00008000UL
+#define APPLETALK_SOCKET__SHUTDOWN                0x00010000UL
+#define APPLETALK_SOCKET__RECVFROM                0x00020000UL
+#define APPLETALK_SOCKET__SENDTO                  0x00040000UL
+#define APPLETALK_SOCKET__RECV_MSG                0x00080000UL
+#define APPLETALK_SOCKET__SEND_MSG                0x00100000UL
+#define APPLETALK_SOCKET__NAME_BIND               0x00200000UL
+
diff -puN security/selinux/include/class_to_string.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/class_to_string.h
--- devel/security/selinux/include/class_to_string.h~selinux-add-security-class-for-appletalk-sockets	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/class_to_string.h	2006-06-01 20:31:49.000000000 -0700
@@ -58,3 +58,4 @@
     S_("nscd")
     S_("association")
     S_("netlink_kobject_uevent_socket")
+    S_("appletalk_socket")
diff -puN security/selinux/include/flask.h~selinux-add-security-class-for-appletalk-sockets security/selinux/include/flask.h
--- devel/security/selinux/include/flask.h~selinux-add-security-class-for-appletalk-sockets	2006-06-01 20:31:49.000000000 -0700
+++ devel-akpm/security/selinux/include/flask.h	2006-06-01 20:31:49.000000000 -0700
@@ -60,6 +60,7 @@
 #define SECCLASS_NSCD                                    53
 #define SECCLASS_ASSOCIATION                             54
 #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET           55
+#define SECCLASS_APPLETALK_SOCKET                        56
 
 /*
  * Security identifier indices for initial entities
_

^ permalink raw reply

* [patch 15/17] pppoe: missing result check in __pppoe_xmit()
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, fmalita, mostrows


From: Florin Malita <fmalita@gmail.com>

skb_clone() may fail, we should check the result.

Coverity CID: 1215.

Signed-off-by: Florin Malita <fmalita@gmail.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: <mostrows@speakeasy.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/net/pppoe.c |    3 +++
 1 file changed, 3 insertions(+)

diff -puN drivers/net/pppoe.c~pppoe-missing-result-check-in-__pppoe_xmit drivers/net/pppoe.c
--- devel/drivers/net/pppoe.c~pppoe-missing-result-check-in-__pppoe_xmit	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/drivers/net/pppoe.c	2006-06-01 20:31:50.000000000 -0700
@@ -861,6 +861,9 @@ static int __pppoe_xmit(struct sock *sk,
 		 * give dev_queue_xmit something it can free.
 		 */
 		skb2 = skb_clone(skb, GFP_ATOMIC);
+
+		if (skb2 == NULL)
+			goto abort;
 	}
 
 	ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr));
_

^ permalink raw reply

* [patch 13/17] secmark: Add new packet controls to SELinux
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, jmorris, sds


From: James Morris <jmorris@namei.org>

Add new per-packet access controls to SELinux, replacing the old packet
controls.

Packets are labeled with the iptables SECMARK and CONNSECMARK targets, then
security policy for the packets is enforced with these controls.

To allow for a smooth transition to the new controls, the old code is still
present, but not active by default.  To restore previous behavior, the old
controls may be activated at runtime by writing a '1' to /selinux/compat_net,
and also via the kernel boot parameter selinux_compat_net.  Switching between
the network control models requires the security load_policy permission.  The
old controls will probably eventually be removed and any continued use is
discouraged.

With this patch, the new secmark controls for SElinux are disabled by default,
so existing behavior is entirely preserved, and the user is not affected at
all.

It also provides a config option to enable the secmark controls by default
(which can always be overridden at boot and runtime).  It is also noted in the
kconfig help that the user will need updated userspace if enabling secmark
controls for SELinux and that they'll probably need the SECMARK and CONNMARK
targets, and conntrack protocol helpers, although such decisions are beyond
the scope of kernel configuration.

Signed-off-by: James Morris <jmorris@namei.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 Documentation/kernel-parameters.txt |    9 
 security/selinux/Kconfig            |   29 +++
 security/selinux/hooks.c            |  242 ++++++++++++++------------
 security/selinux/include/xfrm.h     |    2 
 security/selinux/selinuxfs.c        |   66 +++++++
 security/selinux/xfrm.c             |   12 -
 6 files changed, 241 insertions(+), 119 deletions(-)

diff -puN Documentation/kernel-parameters.txt~secmark-add-new-packet-controls-to-selinux Documentation/kernel-parameters.txt
--- devel/Documentation/kernel-parameters.txt~secmark-add-new-packet-controls-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/Documentation/kernel-parameters.txt	2006-06-01 20:31:50.000000000 -0700
@@ -1405,6 +1405,15 @@ running once the system is up.
 			If enabled at boot time, /selinux/disable can be used
 			later to disable prior to initial policy load.
 
+	selinux_compat_net =
+			[SELINUX] Set initial selinux_compat_net flag value.
+                        Format: { "0" | "1" }
+                        0 -- use new secmark-based packet controls
+                        1 -- use legacy packet controls
+                        Default value is 0 (preferred).
+                        Value can be changed at runtime via
+                        /selinux/compat_net.
+
 	serialnumber	[BUGS=IA-32]
 
 	sg_def_reserved_size=	[SCSI]
diff -puN security/selinux/hooks.c~secmark-add-new-packet-controls-to-selinux security/selinux/hooks.c
--- devel/security/selinux/hooks.c~secmark-add-new-packet-controls-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/hooks.c	2006-06-01 20:31:50.000000000 -0700
@@ -80,6 +80,7 @@
 
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+extern int selinux_compat_net;
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 int selinux_enforcing = 0;
@@ -3216,47 +3217,17 @@ static int selinux_socket_unix_may_send(
 	return 0;
 }
 
-static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
+		struct avc_audit_data *ad, u32 sock_sid, u16 sock_class,
+		u16 family, char *addrp, int len)
 {
-	u16 family;
-	char *addrp;
-	int len, err = 0;
+	int err = 0;
 	u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
-	u32 sock_sid = 0;
-	u16 sock_class = 0;
-	struct socket *sock;
-	struct net_device *dev;
-	struct avc_audit_data ad;
-
-	family = sk->sk_family;
-	if (family != PF_INET && family != PF_INET6)
-		goto out;
-
-	/* Handle mapped IPv4 packets arriving via IPv6 sockets */
-	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
-		family = PF_INET;
-
- 	read_lock_bh(&sk->sk_callback_lock);
- 	sock = sk->sk_socket;
- 	if (sock) {
- 		struct inode *inode;
- 		inode = SOCK_INODE(sock);
- 		if (inode) {
- 			struct inode_security_struct *isec;
- 			isec = inode->i_security;
- 			sock_sid = isec->sid;
- 			sock_class = isec->sclass;
- 		}
- 	}
- 	read_unlock_bh(&sk->sk_callback_lock);
- 	if (!sock_sid)
-  		goto out;
 
-	dev = skb->dev;
-	if (!dev)
+	if (!skb->dev)
 		goto out;
 
-	err = sel_netif_sids(dev, &if_sid, NULL);
+	err = sel_netif_sids(skb->dev, &if_sid, NULL);
 	if (err)
 		goto out;
 
@@ -3279,44 +3250,88 @@ static int selinux_socket_sock_rcv_skb(s
 		break;
 	}
 
-	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, 1);
-	if (err)
-		goto out;
-
-	err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
+	err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
 	if (err)
 		goto out;
 	
-	/* Fixme: this lookup is inefficient */
 	err = security_node_sid(family, addrp, len, &node_sid);
 	if (err)
 		goto out;
 	
-	err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad);
+	err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad);
 	if (err)
 		goto out;
 
 	if (recv_perm) {
 		u32 port_sid;
 
-		/* Fixme: make this more efficient */
 		err = security_port_sid(sk->sk_family, sk->sk_type,
-		                        sk->sk_protocol, ntohs(ad.u.net.sport),
+		                        sk->sk_protocol, ntohs(ad->u.net.sport),
 		                        &port_sid);
 		if (err)
 			goto out;
 
 		err = avc_has_perm(sock_sid, port_sid,
-				   sock_class, recv_perm, &ad);
+				   sock_class, recv_perm, ad);
 	}
 
-	if (!err)
-		err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+out:
+	return err;
+}
+
+static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+	u16 family;
+	u16 sock_class = 0;
+	char *addrp;
+	int len, err = 0;
+	u32 sock_sid = 0;
+	struct socket *sock;
+	struct avc_audit_data ad;
+
+	family = sk->sk_family;
+	if (family != PF_INET && family != PF_INET6)
+		goto out;
+
+	/* Handle mapped IPv4 packets arriving via IPv6 sockets */
+	if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
+		family = PF_INET;
+
+ 	read_lock_bh(&sk->sk_callback_lock);
+ 	sock = sk->sk_socket;
+ 	if (sock) {
+ 		struct inode *inode;
+ 		inode = SOCK_INODE(sock);
+ 		if (inode) {
+ 			struct inode_security_struct *isec;
+ 			isec = inode->i_security;
+ 			sock_sid = isec->sid;
+ 			sock_class = isec->sclass;
+ 		}
+ 	}
+ 	read_unlock_bh(&sk->sk_callback_lock);
+ 	if (!sock_sid)
+  		goto out;
+
+	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;
+
+	if (selinux_compat_net)
+		err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid,
+						  sock_class, family,
+						  addrp, len);
+	else
+		err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET,
+				   PACKET__RECV, &ad);
+	if (err)
+		goto out;
 
+	err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
 out:	
 	return err;
 }
@@ -3456,42 +3471,18 @@ out:
 
 #ifdef CONFIG_NETFILTER
 
-static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
-                                              struct sk_buff **pskb,
-                                              const struct net_device *in,
-                                              const struct net_device *out,
-                                              int (*okfn)(struct sk_buff *),
-                                              u16 family)
+static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
+					    struct inode_security_struct *isec,
+					    struct avc_audit_data *ad,
+					    u16 family, char *addrp, int len)
 {
-	char *addrp;
-	int len, err = NF_ACCEPT;
+	int err;
 	u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
-	struct sock *sk;
-	struct socket *sock;
-	struct inode *inode;
-	struct sk_buff *skb = *pskb;
-	struct inode_security_struct *isec;
-	struct avc_audit_data ad;
-	struct net_device *dev = (struct net_device *)out;
 	
-	sk = skb->sk;
-	if (!sk)
-		goto out;
-		
-	sock = sk->sk_socket;
-	if (!sock)
-		goto out;
-		
-	inode = SOCK_INODE(sock);
-	if (!inode)
-		goto out;
-
 	err = sel_netif_sids(dev, &if_sid, NULL);
 	if (err)
 		goto out;
 
-	isec = inode->i_security;
-	
 	switch (isec->sclass) {
 	case SECCLASS_UDP_SOCKET:
 		netif_perm = NETIF__UDP_SEND;
@@ -3511,55 +3502,88 @@ static unsigned int selinux_ip_postroute
 		break;
 	}
 
-
-	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) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
-		goto out;
-
-	err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
-	                   netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
+	err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+	if (err)
 		goto out;
 		
-	/* Fixme: this lookup is inefficient */
-	err = security_node_sid(family, addrp, len,
-				&node_sid) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
+	err = security_node_sid(family, addrp, len, &node_sid);
+	if (err)
 		goto out;
 	
-	err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
-	                   node_perm, &ad) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
+	err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
+	if (err)
 		goto out;
 
 	if (send_perm) {
 		u32 port_sid;
 		
-		/* Fixme: make this more efficient */
 		err = security_port_sid(sk->sk_family,
 		                        sk->sk_type,
 		                        sk->sk_protocol,
-		                        ntohs(ad.u.net.dport),
-		                        &port_sid) ? NF_DROP : NF_ACCEPT;
-		if (err != NF_ACCEPT)
+		                        ntohs(ad->u.net.dport),
+		                        &port_sid);
+		if (err)
 			goto out;
 
 		err = avc_has_perm(isec->sid, port_sid, isec->sclass,
-		                   send_perm, &ad) ? NF_DROP : NF_ACCEPT;
+				   send_perm, ad);
 	}
+out:
+	return err;
+}
+
+static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
+                                              struct sk_buff **pskb,
+                                              const struct net_device *in,
+                                              const struct net_device *out,
+                                              int (*okfn)(struct sk_buff *),
+                                              u16 family)
+{
+	char *addrp;
+	int len, err = 0;
+	struct sock *sk;
+	struct socket *sock;
+	struct inode *inode;
+	struct sk_buff *skb = *pskb;
+	struct inode_security_struct *isec;
+	struct avc_audit_data ad;
+	struct net_device *dev = (struct net_device *)out;
 
-	if (err != NF_ACCEPT)
+	sk = skb->sk;
+	if (!sk)
 		goto out;
 
-	err = selinux_xfrm_postroute_last(isec->sid, skb);
+	sock = sk->sk_socket;
+	if (!sock)
+		goto out;
+
+	inode = SOCK_INODE(sock);
+	if (!inode)
+		goto out;
+
+	isec = inode->i_security;
+
+	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;
+
+	if (selinux_compat_net)
+		err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad,
+						       family, addrp, len);
+	else
+		err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET,
+				   PACKET__SEND, &ad);
 
+	if (err)
+		goto out;
+
+	err = selinux_xfrm_postroute_last(isec->sid, skb);
 out:
-	return err;
+	return err ? NF_DROP : NF_ACCEPT;
 }
 
 static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
diff -puN security/selinux/include/xfrm.h~secmark-add-new-packet-controls-to-selinux security/selinux/include/xfrm.h
--- devel/security/selinux/include/xfrm.h~secmark-add-new-packet-controls-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/include/xfrm.h	2006-06-01 20:31:50.000000000 -0700
@@ -49,7 +49,7 @@ static inline int selinux_xfrm_sock_rcv_
 
 static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
 {
-	return NF_ACCEPT;
+	return 0;
 }
 
 static inline int selinux_socket_getpeer_stream(struct sock *sk)
diff -puN security/selinux/Kconfig~secmark-add-new-packet-controls-to-selinux security/selinux/Kconfig
--- devel/security/selinux/Kconfig~secmark-add-new-packet-controls-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/Kconfig	2006-06-01 20:31:50.000000000 -0700
@@ -1,6 +1,7 @@
 config SECURITY_SELINUX
 	bool "NSA SELinux Support"
 	depends on SECURITY_NETWORK && AUDIT && NET && INET
+	select NETWORK_SECMARK
 	default n
 	help
 	  This selects NSA Security-Enhanced Linux (SELinux).
@@ -95,3 +96,31 @@ config SECURITY_SELINUX_CHECKREQPROT_VAL
 	  via /selinux/checkreqprot if authorized by policy.
 
 	  If you are unsure how to answer this question, answer 1.
+
+config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+	bool "NSA SELinux enable new secmark network controls by default"
+	depends on SECURITY_SELINUX
+	default n
+	help
+	  This option determines whether the new secmark-based network
+	  controls will be enabled by default.  If not, the old internal
+	  per-packet controls will be enabled by default, preserving
+	  old behavior.
+
+	  If you enable the new controls, you will need updated
+	  SELinux userspace libraries, tools and policy.  Typically,
+	  your distribution will provide these and enable the new controls
+	  in the kernel they also distribute.
+
+	  Note that this option can be overriden at boot with the
+	  selinux_compat_net parameter, and after boot via
+	  /selinux/compat_net.  See Documentation/kernel-parameters.txt
+	  for details on this parameter.
+
+	  If you enable the new network controls, you will likely
+	  also require the SECMARK and CONNSECMARK targets, as
+	  well as any conntrack helpers for protocols which you
+	  wish to control.
+
+	  If you are unsure what do do here, select N.
+
diff -puN security/selinux/selinuxfs.c~secmark-add-new-packet-controls-to-selinux security/selinux/selinuxfs.c
--- devel/security/selinux/selinuxfs.c~secmark-add-new-packet-controls-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/selinuxfs.c	2006-06-01 20:31:50.000000000 -0700
@@ -38,6 +38,14 @@
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
+#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+#define SELINUX_COMPAT_NET_VALUE 0
+#else
+#define SELINUX_COMPAT_NET_VALUE 1
+#endif
+
+int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
+
 static int __init checkreqprot_setup(char *str)
 {
 	selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
@@ -45,6 +53,13 @@ static int __init checkreqprot_setup(cha
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
+static int __init selinux_compat_net_setup(char *str)
+{
+	selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
+	return 1;
+}
+__setup("selinux_compat_net=", selinux_compat_net_setup);
+
 
 static DEFINE_MUTEX(sel_mutex);
 
@@ -85,6 +100,7 @@ enum sel_inos {
 	SEL_AVC,	/* AVC management directory */
 	SEL_MEMBER,	/* compute polyinstantiation membership decision */
 	SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
+	SEL_COMPAT_NET,	/* whether to use old compat network packet controls */
 };
 
 #define TMPBUFLEN	12
@@ -364,6 +380,55 @@ static struct file_operations sel_checkr
 	.write		= sel_write_checkreqprot,
 };
 
+static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	char tmpbuf[TMPBUFLEN];
+	ssize_t length;
+
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
+				    size_t count, loff_t *ppos)
+{
+	char *page;
+	ssize_t length;
+	int new_value;
+
+	length = task_has_security(current, SECURITY__LOAD_POLICY);
+	if (length)
+		return length;
+
+	if (count >= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	page = (char*)get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	length = -EFAULT;
+	if (copy_from_user(page, buf, count))
+		goto out;
+
+	length = -EINVAL;
+	if (sscanf(page, "%d", &new_value) != 1)
+		goto out;
+
+	selinux_compat_net = new_value ? 1 : 0;
+	length = count;
+out:
+	free_page((unsigned long) page);
+	return length;
+}
+static struct file_operations sel_compat_net_ops = {
+	.read		= sel_read_compat_net,
+	.write		= sel_write_compat_net,
+};
+
 /*
  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
  */
@@ -1219,6 +1284,7 @@ static int sel_fill_super(struct super_b
 		[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
 		[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
 		[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
+		[SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
 		/* last one */ {""}
 	};
 	ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff -puN security/selinux/xfrm.c~secmark-add-new-packet-controls-to-selinux security/selinux/xfrm.c
--- devel/security/selinux/xfrm.c~secmark-add-new-packet-controls-to-selinux	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/security/selinux/xfrm.c	2006-06-01 20:31:50.000000000 -0700
@@ -356,18 +356,12 @@ int selinux_xfrm_postroute_last(u32 isec
 			struct xfrm_state *x = dst_test->xfrm;
 
 			if (x && selinux_authorizable_xfrm(x))
-				goto accept;
+				goto out;
 		}
 	}
 
 	rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
 			  ASSOCIATION__SENDTO, NULL);
-	if (rc)
-		goto drop;
-
-accept:
-	return NF_ACCEPT;
-
-drop:
-	return NF_DROP;
+out:
+	return rc;
 }
_

^ permalink raw reply

* [patch 17/17] recent match: missing refcnt initialization
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, kaber


From: Patrick McHardy <kaber@trash.net>

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 net/ipv4/netfilter/ipt_recent.c |    1 +
 1 file changed, 1 insertion(+)

diff -puN net/ipv4/netfilter/ipt_recent.c~recent-match-missing-refcnt-initialization net/ipv4/netfilter/ipt_recent.c
--- devel/net/ipv4/netfilter/ipt_recent.c~recent-match-missing-refcnt-initialization	2006-06-01 20:31:51.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ipt_recent.c	2006-06-01 20:31:51.000000000 -0700
@@ -262,6 +262,7 @@ ipt_recent_checkentry(const char *tablen
 		    GFP_KERNEL);
 	if (t == NULL)
 		goto out;
+	t->refcnt = 1;
 	strcpy(t->name, info->name);
 	INIT_LIST_HEAD(&t->lru_list);
 	for (i = 0; i < ip_list_hash_size; i++)
_

^ permalink raw reply

* [patch 16/17] recent match: fix "sleeping function called from invalid context"
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, kaber


From: Patrick McHardy <kaber@trash.net>

create_proc_entry must not be called with locks held.  Use a mutex instead
to protect data only changed in user context.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 net/ipv4/netfilter/ipt_recent.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff -puN net/ipv4/netfilter/ipt_recent.c~recent-match-fix-sleeping-function-called-from-invalid-context net/ipv4/netfilter/ipt_recent.c
--- devel/net/ipv4/netfilter/ipt_recent.c~recent-match-fix-sleeping-function-called-from-invalid-context	2006-06-01 20:31:51.000000000 -0700
+++ devel-akpm/net/ipv4/netfilter/ipt_recent.c	2006-06-01 20:31:51.000000000 -0700
@@ -69,6 +69,7 @@ struct recent_table {
 
 static LIST_HEAD(tables);
 static DEFINE_SPINLOCK(recent_lock);
+static DEFINE_MUTEX(recent_mutex);
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry	*proc_dir;
@@ -249,7 +250,7 @@ ipt_recent_checkentry(const char *tablen
 	    strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
 		return 0;
 
-	spin_lock_bh(&recent_lock);
+	mutex_lock(&recent_mutex);
 	t = recent_table_lookup(info->name);
 	if (t != NULL) {
 		t->refcnt++;
@@ -258,7 +259,7 @@ ipt_recent_checkentry(const char *tablen
 	}
 
 	t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
-		    GFP_ATOMIC);
+		    GFP_KERNEL);
 	if (t == NULL)
 		goto out;
 	strcpy(t->name, info->name);
@@ -274,10 +275,12 @@ ipt_recent_checkentry(const char *tablen
 	t->proc->proc_fops = &recent_fops;
 	t->proc->data      = t;
 #endif
+	spin_lock_bh(&recent_lock);
 	list_add_tail(&t->list, &tables);
+	spin_unlock_bh(&recent_lock);
 	ret = 1;
 out:
-	spin_unlock_bh(&recent_lock);
+	mutex_unlock(&recent_mutex);
 	return ret;
 }
 
@@ -288,17 +291,19 @@ ipt_recent_destroy(const struct xt_match
 	const struct ipt_recent_info *info = matchinfo;
 	struct recent_table *t;
 
-	spin_lock_bh(&recent_lock);
+	mutex_lock(&recent_mutex);
 	t = recent_table_lookup(info->name);
 	if (--t->refcnt == 0) {
+		spin_lock_bh(&recent_lock);
 		list_del(&t->list);
+		spin_unlock_bh(&recent_lock);
 		recent_table_flush(t);
 #ifdef CONFIG_PROC_FS
 		remove_proc_entry(t->name, proc_dir);
 #endif
 		kfree(t);
 	}
-	spin_unlock_bh(&recent_lock);
+	mutex_unlock(&recent_mutex);
 }
 
 #ifdef CONFIG_PROC_FS
_

^ permalink raw reply

* [patch 14/17] irda: missing allocation result check in irlap_change_speed()
From: akpm @ 2006-06-02  3:32 UTC (permalink / raw)
  To: davem; +Cc: netdev, akpm, fmalita, samuel


From: Florin Malita <fmalita@gmail.com>

The skb allocation may fail, which can result in a NULL pointer dereference
in irlap_queue_xmit().

Coverity CID: 434.

davem: "If the allocation fails we should probably do something more
interesting here, such as schedule a timer to try again later.  Otherwise the
speed change will silently never occur."

Signed-off-by: Florin Malita <fmalita@gmail.com>
Cc: Samuel Ortiz <samuel@sortiz.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 net/irda/irlap.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff -puN net/irda/irlap.c~irda-missing-allocation-result-check-in-irlap_change_speed net/irda/irlap.c
--- devel/net/irda/irlap.c~irda-missing-allocation-result-check-in-irlap_change_speed	2006-06-01 20:31:50.000000000 -0700
+++ devel-akpm/net/irda/irlap.c	2006-06-01 20:31:50.000000000 -0700
@@ -884,7 +884,8 @@ static void irlap_change_speed(struct ir
 	if (now) {
 		/* Send down empty frame to trigger speed change */
 		skb = dev_alloc_skb(0);
-		irlap_queue_xmit(self, skb);
+		if (skb)
+			irlap_queue_xmit(self, skb);
 	}
 }
 
_

^ permalink raw reply

* Re: [patch 16/17] recent match: fix "sleeping function called from invalid context"
From: Andrew Morton @ 2006-06-02  3:34 UTC (permalink / raw)
  To: davem, netdev, kaber
In-Reply-To: <200606020328.k523SKhS028868@shell0.pdx.osdl.net>


oops, sorry, I didn't mean to send 16 and 17.

^ permalink raw reply

* Re: orinoco encodeext + auth patch on lkml
From: Pavel Roskin @ 2006-06-02  5:38 UTC (permalink / raw)
  To: Dan Williams; +Cc: netdev
In-Reply-To: <1149076999.2805.2.camel@localhost.localdomain>

Hello, Dan!

On Wed, 2006-05-31 at 08:03 -0400, Dan Williams wrote:
> Pavel,
> 
> Unsure if you saw this.  Slightly annoying he didn't send to netdev, but
> would be good to take a look at and possibly integrate.  Looks sane to
> me from 10,000ft.
> 
> http://lkml.org/lkml/2006/5/30/433

Thanks for heads up.  Actually, this e-mail was copied to the orinoco
mailing list, so I'm aware of it.

-- 
Regards,
Pavel Roskin


^ permalink raw reply

* Re: [patch, -rc5-mm1] lock validator: special locking: net/ipv4/igmp.c #2
From: Jesse Brandeburg @ 2006-06-02  6:47 UTC (permalink / raw)
  To: Ingo Molnar; +Cc: Linux-Kernel,, Andrew Morton, Arjan van de Ven, NetDEV list
In-Reply-To: <20060601063537.GA19931@elte.hu>

On 5/31/06, Ingo Molnar <mingo@elte.hu> wrote:
>
> * Jesse Brandeburg <jesse.brandeburg@gmail.com> wrote:
>
> > well, when running e1000 through some code paths on FC4 +
> > 2.6.17-rc5-mm1 + ingo's latest rollup patch, with this lockdep debug
> > option enabled I got this:
> >
> > e1000: eth1: e1000_watchdog_task: NIC Link is Up 1000 Mbps Full Duplex
> >
> > ======================================
> > [ BUG: bad unlock ordering detected! ]
> > --------------------------------------
> > mDNSResponder/2361 is trying to release lock (&in_dev->mc_list_lock) at:
> > [<ffffffff81233f5a>] ip_mc_add_src+0x85/0x1f8
>
> ok, could you try the patch below? (i also updated the rollup with this
> fix)
>
>         Ingo
>
> ---------------------
> Subject: lock validator: special locking: net/ipv4/igmp.c #2
> From: Ingo Molnar <mingo@elte.hu>
>
> another case of non-nested unlocking igmp.c.
>
> Signed-off-by: Ingo Molnar <mingo@elte.hu>
> ---
>  net/ipv4/igmp.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> Index: linux/net/ipv4/igmp.c
> ===================================================================
> --- linux.orig/net/ipv4/igmp.c
> +++ linux/net/ipv4/igmp.c
> @@ -1646,7 +1646,7 @@ static int ip_mc_add_src(struct in_devic
>                 return -ESRCH;
>         }
>         spin_lock_bh(&pmc->lock);
> -       read_unlock(&in_dev->mc_list_lock);
> +       read_unlock_non_nested(&in_dev->mc_list_lock);
>
>  #ifdef CONFIG_IP_MULTICAST
>         sf_markstate(pmc);
>

yep, this fixes it.

^ permalink raw reply

* Re: Question about tcp hash function tcp_hashfn()
From: Evgeniy Polyakov @ 2006-06-02  7:01 UTC (permalink / raw)
  To: David Miller, draghuram, linux-kernel, netdev; +Cc: Brian F. G. Bidulock
In-Reply-To: <20060601124010.C554@openss7.org>

On Thu, Jun 01, 2006 at 12:40:10PM -0600, Brian F. G. Bidulock (bidulock@openss7.org) wrote:
> So what are your thoughts about my sequence number approach (for
> connected sockets)?

Depending on how you are going to use it.
Generic socket code does not have TCP sequence numbers since it must
work with all supported protocols.
Netchannels also do not know about internals of the packet by design,
since all protocol processing is performed at the end peer.

Sequence number can be wrapped in minutes in current networks and even
faster tomorrow, that is why PAWS was created.

Your idea about reinserting the socket does not scale in 1Gbit
environment, and definitely will not in 10Gbit.

Probably it is possible to create second hash table for TCP sockets only
and use that table first in protocol handler, but it requires some
research to prove the idea.

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Re: Question about tcp hash function tcp_hashfn()
From: Florian Weimer @ 2006-06-02  5:40 UTC (permalink / raw)
  To: Evgeniy Polyakov
  Cc: David Miller, draghuram, linux-kernel, netdev,
	Brian F. G. Bidulock
In-Reply-To: <20060601060424.GA28087@2ka.mipt.ru>

* Evgeniy Polyakov:

> That is wrong. And I have a code and picture to show that, 
> and you dont - prove me wrong :)

Here we go:

static inline num2ip(__u8 a1, __u8 a2, __u8 a3, __u8 a4)
{
	__u32 a = 0;

	a |= a1;
	a << 8;
	a |= a2;
	a << 8;
	a |= a3;
	a << 8;
	a |= a4;

	return a;
}

"gcc -Wall" was pretty illuminating. 8-P After fixing this and
switching to a better PRNG, I get something which looks pretty normal.

^ permalink raw reply

* Re: Question about tcp hash function tcp_hashfn()
From: Evgeniy Polyakov @ 2006-06-02  7:48 UTC (permalink / raw)
  To: Florian Weimer
  Cc: David Miller, draghuram, linux-kernel, netdev,
	Brian F. G. Bidulock
In-Reply-To: <87y7wgaze1.fsf@mid.deneb.enyo.de>

On Fri, Jun 02, 2006 at 07:40:38AM +0200, Florian Weimer (fw@deneb.enyo.de) wrote:
> * Evgeniy Polyakov:
> 
> > That is wrong. And I have a code and picture to show that, 
> > and you dont - prove me wrong :)
> 
> Here we go:
> 
> static inline num2ip(__u8 a1, __u8 a2, __u8 a3, __u8 a4)
> {
> 	__u32 a = 0;
> 
> 	a |= a1;
> 	a << 8;
> 	a |= a2;
> 	a << 8;
> 	a |= a3;
> 	a << 8;
> 	a |= a4;
> 
> 	return a;
> }
> 
> "gcc -Wall" was pretty illuminating. 8-P After fixing this and
> switching to a better PRNG, I get something which looks pretty normal.

:) thats true, but to be 100% honest I used different code to test for
hash artifacts...
That code was created to show that it is possible to _have_ artifacts,
but not specially to _find_ them.

But it still does not fix artifacts with for example const IP and random
ports or const IP and linear port selection.

Values must be specially tuned to be used with Jenkins hash, for example
linear port with const IP produce following hash buckets:
100 24397
200 12112
300 3952
400 975
500 178
600 40
700 3
800 1

i.e. one 800-entries bucket (!) while xor one always have only 100 of
them (for 100*hash_size number of iterations).

So, your prove does not valid :)

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Netchannel: TCP memcpy() to mapped are support. Benchmarks.
From: Evgeniy Polyakov @ 2006-06-02  9:37 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, caitlinb, kelly, rusty

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

Hello, developers.

Attached initial benchmark of netchannel with memcpy() into kernelspace
area, which could be mapped from userspace versus socket code using
1gbit link.

As you can see from the graph, netchannels outperforms sockets in speed, 
but it's CPU usage is higher too.
It is possible, that it is the price, i.e. socket code would increase
it's CPU usage if it could increase it's processing speed.

Implementationis fairly ugly yet. It is required a some changes in 
generic TCP state machine processing logic to clean things up, 
so it would be performed not on top of sockets, 
but using skbs from queues with appropriate parameters (timeout,
flags) provided either as new structure (so it would be embedded into 
struct sock and netchannel) or as function parameters.

Netchannels currently use two queue dereferencings to work with socket's
queue processing: 
- from netchannel's queue which is filled in interrupt
- from socket's queue which is filled in process context

which is a source of some speed problems too.

It still requires some thinking...

-- 
	Evgeniy Polyakov

[-- Attachment #2: netchannel_speed.png --]
[-- Type: image/png, Size: 8322 bytes --]

^ permalink raw reply

* Re: [PATCH] softmac: Fix handling of authentication failure
From: Daniel Drake @ 2006-06-02 10:09 UTC (permalink / raw)
  To: Larry Finger; +Cc: linville, netdev, johannes
In-Reply-To: <447FA5B5.8020707@lwfinger.net>

Larry Finger wrote:
> This statement fails to compile on my system using Linus' tree, because 
> ieee80211softmac_disassoc needs a second argument - the reason. It seems 
> as if WLAN_REASON_PREV_AUTH_NOT_VALID would be appropriate.

Thanks for pointing that out. This patch depends on a patch titled 
"softmac: deauthentication implies deassociation" which is apparently 
not present in Linus' tree.

Daniel

^ permalink raw reply

* Netchannel: TCP memcpy() to mapped support. Patch.
From: Evgeniy Polyakov @ 2006-06-02 10:29 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, caitlinb, kelly, rusty
In-Reply-To: <20060602093739.GA6770@2ka.mipt.ru>

Hello, developers.

Attached netchannel psubsystem patch which implements TCP memcpy()
(into preallocated area which could be mapped) reading and 
UDP copy_to_user()/memcpy() reading.

Implementations fairly ugly yet. 

Netchannels currently use two queue dereferencings to work with socket's
queue processing: 
- from netchannel's queue which is filled in interrupt
- from socket's queue which is filled in process context

Patch, userspace and implementation details can be found 
on netchannel homepage:

http://tservice.net.ru/~s0mbre/old/?section=projects&item=netchannel

Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>

diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index f48bef1..7a4a758 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -315,3 +315,5 @@ ENTRY(sys_call_table)
 	.long sys_splice
 	.long sys_sync_file_range
 	.long sys_tee			/* 315 */
+	.long sys_vmsplice
+	.long sys_netchannel_control
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 5a92fed..fdfb997 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -696,4 +696,5 @@ ia32_sys_call_table:
 	.quad sys_sync_file_range
 	.quad sys_tee
 	.quad compat_sys_vmsplice
+	.quad sys_netchannel_control
 ia32_syscall_end:		
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index eb4b152..777cd85 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -322,8 +322,9 @@
 #define __NR_sync_file_range	314
 #define __NR_tee		315
 #define __NR_vmsplice		316
+#define __NR_netchannel_control	317
 
-#define NR_syscalls 317
+#define NR_syscalls 318
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index feb77cb..08c230e 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -617,8 +617,10 @@ __SYSCALL(__NR_tee, sys_tee)
 __SYSCALL(__NR_sync_file_range, sys_sync_file_range)
 #define __NR_vmsplice		278
 __SYSCALL(__NR_vmsplice, sys_vmsplice)
+#define __NR_netchannel_control	279
+__SYSCALL(__NR_vmsplice, sys_netchannel_control)
 
-#define __NR_syscall_max __NR_vmsplice
+#define __NR_syscall_max __NR_netchannel_control
 
 #ifndef __NO_STUBS
 
diff --git a/include/linux/netchannel.h b/include/linux/netchannel.h
new file mode 100644
index 0000000..abb0b8d
--- /dev/null
+++ b/include/linux/netchannel.h
@@ -0,0 +1,102 @@
+/*
+ * 	netchannel.h
+ * 
+ * 2006 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __NETCHANNEL_H
+#define __NETCHANNEL_H
+
+#include <linux/types.h>
+
+enum netchannel_commands {
+	NETCHANNEL_CREATE = 0,
+	NETCHANNEL_REMOVE,
+	NETCHANNEL_BIND,
+	NETCHANNEL_READ,
+	NETCHANNEL_DUMP,
+};
+
+enum netchannel_type {
+	NETCHANNEL_COPY_USER = 0,
+	NETCHANNEL_MMAP,
+	NETCHANEL_VM_HACK,
+};
+
+struct unetchannel
+{
+	__u32			src, dst;		/* source/destination hashes */
+	__u16			sport, dport;		/* source/destination ports */
+	__u8			proto;			/* IP protocol number */
+	__u8			type;			/* Netchannel type */
+	__u8			memory_limit_order;	/* Memor limit order */
+	__u8			reserved;
+};
+
+struct unetchannel_control
+{
+	struct unetchannel	unc;
+	__u32			cmd;
+	__u32			len;
+	__u32			flags;
+	__u32			timeout;
+	unsigned int		fd;
+};
+
+#ifdef __KERNEL__
+
+struct netchannel
+{
+	struct hlist_node	node;
+	atomic_t		refcnt;
+	struct rcu_head		rcu_head;
+	struct unetchannel	unc;
+	unsigned long		hit;
+
+	struct page *		(*nc_alloc_page)(unsigned int size);
+	void			(*nc_free_page)(struct page *page);
+	int			(*nc_read_data)(struct netchannel *, unsigned int *timeout, unsigned int *len, void *arg);
+
+	struct sk_buff_head 	recv_queue;
+	wait_queue_head_t	wait;
+
+	unsigned int		qlen;
+
+	void			*priv;
+
+	struct inode 		*inode;
+};
+
+struct netchannel_cache_head
+{
+	struct hlist_head	head;
+	struct mutex		mutex;
+};
+
+#define NETCHANNEL_MAX_ORDER	31
+#define NETCHANNEL_MIN_ORDER	PAGE_SHIFT
+
+struct netchannel_mmap
+{
+	struct page		**page;
+	unsigned int		pnum;
+	unsigned int		poff;
+};
+
+#endif /* __KERNEL__ */
+#endif /* __NETCHANNEL_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a461b51..9924911 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -684,6 +684,15 @@ extern void		dev_queue_xmit_nit(struct s
 
 extern void		dev_init(void);
 
+#ifdef CONFIG_NETCHANNEL
+extern int netchannel_recv(struct sk_buff *skb);
+#else
+static int netchannel_recv(struct sk_buff *skb) 
+{ 
+	return -1;
+}
+#endif
+
 extern int		netdev_nit;
 extern int		netdev_budget;
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f8f2347..69f0c32 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -265,7 +265,8 @@ struct sk_buff {
 				nfctinfo:3;
 	__u8			pkt_type:3,
 				fclone:2,
-				ipvs_property:1;
+				ipvs_property:1,
+				netchannel:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
@@ -314,6 +315,18 @@ static inline struct sk_buff *alloc_skb(
 	return __alloc_skb(size, priority, 0);
 }
 
+#ifdef CONFIG_NETCHANNEL
+struct unetchannel;
+extern struct sk_buff *netchannel_alloc(struct unetchannel *unc, unsigned int header_size, 
+		unsigned int total_size, gfp_t gfp_mask);
+#else
+static struct sk_buff *netchannel_alloc(void *unc, unsigned int header_size, 
+		unsigned int total_size, gfp_t gfp_mask)
+{
+	return NULL;
+}
+#endif
+
 static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
 					       gfp_t priority)
 {
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9ab2ddd..036a221 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -298,6 +298,7 @@ extern int csum_partial_copy_fromiovecen
 
 extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
 extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
+extern int memcpy_toiovec_copy(struct iovec *v, unsigned char *kdata, int len);
 extern int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen);
 extern int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3996960..8c22875 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -582,4 +582,6 @@ asmlinkage long sys_tee(int fdin, int fd
 asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes,
 					unsigned int flags);
 
+asmlinkage long sys_netchannel_control(void __user *arg);
+
 #endif
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 5433195..1747fc3 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -132,3 +132,5 @@ cond_syscall(sys_mincore);
 cond_syscall(sys_madvise);
 cond_syscall(sys_mremap);
 cond_syscall(sys_remap_file_pages);
+
+cond_syscall(sys_netchannel_control);
diff --git a/net/Kconfig b/net/Kconfig
index 4193cdc..465e37b 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -66,6 +66,14 @@ source "net/ipv6/Kconfig"
 
 endif # if INET
 
+config NETCHANNEL
+	bool "Network channels"
+	---help---
+	  Network channels are peer-to-peer abstraction, which allows to create
+	  high performance communications. 
+	  Main advantages are unified address cache, protocol processing moved
+	  to userspace, receiving zero-copy support and other interesting features.
+
 menuconfig NETFILTER
 	bool "Network packet filtering (replaces ipchains)"
 	---help---
diff --git a/net/core/Makefile b/net/core/Makefile
index 79fe12c..7119812 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_NET_DIVERT) += dv.o
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
 obj-$(CONFIG_WIRELESS_EXT) += wireless.o
 obj-$(CONFIG_NETPOLL) += netpoll.o
+obj-$(CONFIG_NETCHANNEL) += netchannel.o
diff --git a/net/core/datagram.c b/net/core/datagram.c
index aecddcc..3db8873 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -235,6 +235,8 @@ void skb_kill_datagram(struct sock *sk, 
 
 EXPORT_SYMBOL(skb_kill_datagram);
 
+typedef int (* copy_iovec_t)(struct iovec *iov, unsigned char *kdata, int len);
+
 /**
  *	skb_copy_datagram_iovec - Copy a datagram to an iovec.
  *	@skb: buffer to copy
@@ -249,12 +251,13 @@ int skb_copy_datagram_iovec(const struct
 {
 	int start = skb_headlen(skb);
 	int i, copy = start - offset;
+	copy_iovec_t func = (skb->netchannel)?&memcpy_toiovec_copy:&memcpy_toiovec;
 
 	/* Copy header. */
 	if (copy > 0) {
 		if (copy > len)
 			copy = len;
-		if (memcpy_toiovec(to, skb->data + offset, copy))
+		if (func(to, skb->data + offset, copy))
 			goto fault;
 		if ((len -= copy) == 0)
 			return 0;
@@ -277,7 +280,7 @@ int skb_copy_datagram_iovec(const struct
 			if (copy > len)
 				copy = len;
 			vaddr = kmap(page);
-			err = memcpy_toiovec(to, vaddr + frag->page_offset +
+			err = func(to, vaddr + frag->page_offset +
 					     offset - start, copy);
 			kunmap(page);
 			if (err)
diff --git a/net/core/dev.c b/net/core/dev.c
index 9ab3cfa..2721111 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1712,6 +1712,10 @@ int netif_receive_skb(struct sk_buff *sk
 		}
 	}
 
+	ret = netchannel_recv(skb);
+	if (!ret)
+		goto out;
+
 #ifdef CONFIG_NET_CLS_ACT
 	if (pt_prev) {
 		ret = deliver_skb(skb, pt_prev, orig_dev);
diff --git a/net/core/iovec.c b/net/core/iovec.c
index 65e4b56..8d19ed7 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -98,6 +98,23 @@ int memcpy_toiovec(struct iovec *iov, un
 	return 0;
 }
 
+int memcpy_toiovec_copy(struct iovec *iov, unsigned char *kdata, int len)
+{
+	while (len > 0) {
+		if (iov->iov_len) {
+			int copy = min_t(unsigned int, iov->iov_len, len);
+			memcpy(iov->iov_base, kdata, copy);
+			kdata += copy;
+			len -= copy;
+			iov->iov_len -= copy;
+			iov->iov_base += copy;
+		}
+		iov++;
+	}
+
+	return 0;
+}
+
 /*
  *	Copy iovec to kernel. Returns -EFAULT on error.
  *
@@ -237,3 +254,4 @@ EXPORT_SYMBOL(csum_partial_copy_fromiove
 EXPORT_SYMBOL(memcpy_fromiovec);
 EXPORT_SYMBOL(memcpy_fromiovecend);
 EXPORT_SYMBOL(memcpy_toiovec);
+EXPORT_SYMBOL(memcpy_toiovec_copy);
diff --git a/net/core/netchannel.c b/net/core/netchannel.c
new file mode 100644
index 0000000..e5493b7
--- /dev/null
+++ b/net/core/netchannel.c
@@ -0,0 +1,1157 @@
+/*
+ * 	netchannel.c
+ * 
+ * 2006 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ * All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/unistd.h>
+#include <linux/linkage.h>
+#include <linux/notifier.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/highmem.h>
+#include <linux/netchannel.h>
+
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include <linux/udp.h>
+
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <net/addrconf.h>
+
+#include <asm/uaccess.h>
+
+static unsigned int netchannel_hash_order = 8;
+static struct netchannel_cache_head ***netchannel_hash_table;
+static kmem_cache_t *netchannel_cache;
+
+static int netchannel_inetaddr_notifier_call(struct notifier_block *, unsigned long, void *);
+static struct notifier_block netchannel_inetaddr_notifier = {
+	.notifier_call = &netchannel_inetaddr_notifier_call
+};
+
+#ifdef CONFIG_IPV6
+static int netchannel_inet6addr_notifier_call(struct notifier_block *, unsigned long, void *);
+static struct notifier_block netchannel_inet6addr_notifier = {
+	.notifier_call = &netchannel_inet6addr_notifier_call
+};
+#endif
+
+static inline unsigned int netchannel_hash(struct unetchannel *unc)
+{
+	unsigned int h = (unc->dst ^ unc->dport) ^ (unc->src ^ unc->sport);
+	h ^= h >> 16;
+	h ^= h >> 8;
+	h ^= unc->proto;
+	return h & ((1 << 2*netchannel_hash_order) - 1);
+}
+
+static inline void netchannel_convert_hash(unsigned int hash, unsigned int *col, unsigned int *row)
+{
+	*row = hash & ((1 << netchannel_hash_order) - 1);
+	*col = (hash >> netchannel_hash_order) & ((1 << netchannel_hash_order) - 1);
+}
+
+static struct netchannel_cache_head *netchannel_bucket(struct unetchannel *unc)
+{
+	unsigned int hash = netchannel_hash(unc);
+	unsigned int col, row;
+
+	netchannel_convert_hash(hash, &col, &row);
+	return netchannel_hash_table[col][row];
+}
+
+static inline int netchannel_hash_equal_full(struct unetchannel *unc1, struct unetchannel *unc2)
+{
+	return (unc1->dport == unc2->dport) && (unc1->dst == unc2->dst) &&
+				(unc1->sport == unc2->sport) && (unc1->src == unc2->src) && 
+				(unc1->proto == unc2->proto);
+}
+
+static inline int netchannel_hash_equal_dest(struct unetchannel *unc1, struct unetchannel *unc2)
+{
+	return ((unc1->dport == unc2->dport) && (unc1->dst == unc2->dst) && (unc1->proto == unc2->proto));
+}
+
+static struct netchannel *netchannel_check_dest(struct unetchannel *unc, struct netchannel_cache_head *bucket)
+{
+	struct netchannel *nc;
+	struct hlist_node *node;
+	int found = 0;
+	
+	hlist_for_each_entry_rcu(nc, node, &bucket->head, node) {
+		if (netchannel_hash_equal_dest(&nc->unc, unc)) {
+			found = 1;
+			break;
+		}
+	}
+
+	return (found)?nc:NULL;
+}
+
+static struct netchannel *netchannel_check_full(struct unetchannel *unc, struct netchannel_cache_head *bucket)
+{
+	struct netchannel *nc;
+	struct hlist_node *node;
+	int found = 0;
+
+	hlist_for_each_entry_rcu(nc, node, &bucket->head, node) {
+		if (netchannel_hash_equal_full(&nc->unc, unc)) {
+			found = 1;
+			break;
+		}
+	}
+
+	return (found)?nc:NULL;
+}
+
+static void netchannel_mmap_cleanup(struct netchannel *nc)
+{
+	unsigned int i;
+	struct netchannel_mmap *m = nc->priv;
+
+	for (i=0; i<m->pnum; ++i)
+		__free_page(m->page[i]);
+
+	kfree(m);
+}
+
+static void netchannel_cleanup(struct netchannel *nc)
+{
+	switch (nc->unc.type) {
+		case NETCHANNEL_COPY_USER:
+			break;
+		case NETCHANNEL_MMAP:
+			netchannel_mmap_cleanup(nc);
+			break;
+		default:
+			break;
+	}
+}
+
+static void netchannel_free_rcu(struct rcu_head *rcu)
+{
+	struct netchannel *nc = container_of(rcu, struct netchannel, rcu_head);
+
+	netchannel_cleanup(nc);
+	kmem_cache_free(netchannel_cache, nc);
+}
+
+static inline void netchannel_get(struct netchannel *nc)
+{
+	atomic_inc(&nc->refcnt);
+}
+
+static inline void netchannel_put(struct netchannel *nc)
+{
+	if (atomic_dec_and_test(&nc->refcnt))
+		call_rcu(&nc->rcu_head, &netchannel_free_rcu);
+}
+
+static inline void netchannel_dump_info_unc(struct unetchannel *unc, char *prefix, unsigned long hit, int err)
+{
+	u32 src, dst;
+	u16 sport, dport;
+	
+	dst = unc->dst;
+	src = unc->src;
+	dport = ntohs(unc->dport);
+	sport = ntohs(unc->sport);
+
+	printk(KERN_NOTICE "netchannel: %s %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u, "
+			"proto: %u, type: %u, order: %u, hit: %lu, err: %d.\n",
+			prefix, NIPQUAD(src), sport, NIPQUAD(dst), dport, 
+			unc->proto, unc->type, unc->memory_limit_order, hit, err);
+}
+
+static int netchannel_convert_skb_ipv6(struct sk_buff *skb, struct unetchannel *unc)
+{
+	/*
+	 * Hash IP addresses into src/dst. Setup TCP/UDP ports.
+	 * Not supported yet.
+	 */
+	return -1;
+}
+
+static int netchannel_convert_skb_ipv4(struct sk_buff *skb, struct unetchannel *unc)
+{
+	struct iphdr *iph;
+	u32 len;
+	struct tcphdr *th;
+	struct udphdr *uh;
+
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto inhdr_error;
+
+	iph = skb->nh.iph;
+
+	if (iph->ihl < 5 || iph->version != 4)
+		goto inhdr_error;
+
+	if (!pskb_may_pull(skb, iph->ihl*4))
+		goto inhdr_error;
+
+	iph = skb->nh.iph;
+
+	if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl)))
+		goto inhdr_error;
+
+	len = ntohs(iph->tot_len);
+	if (skb->len < len || len < (iph->ihl*4))
+		goto inhdr_error;
+
+	if (pskb_trim_rcsum(skb, len))
+		goto inhdr_error;
+
+	unc->dst = iph->daddr;
+	unc->src = iph->saddr;
+	unc->proto = iph->protocol;
+
+	len = skb->len;
+
+	skb->h.raw = skb->nh.raw + iph->ihl*4;
+
+	switch (unc->proto) {
+		case IPPROTO_TCP:
+			if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
+				goto inhdr_error;
+			th = skb->h.th;
+
+			if (th->doff < sizeof(struct tcphdr) / 4)
+				goto inhdr_error;
+
+			unc->dport = th->dest;
+			unc->sport = th->source;
+			break;
+		case IPPROTO_UDP:
+			if (!pskb_may_pull(skb, sizeof(struct udphdr)))
+				goto inhdr_error;
+			uh = skb->h.uh;
+
+			if (ntohs(uh->len) < sizeof(struct udphdr))
+				goto inhdr_error;
+
+			unc->dport = uh->dest;
+			unc->sport = uh->source;
+			break;
+		default:
+			goto inhdr_error;
+	}
+
+	return 0;
+
+inhdr_error:
+	return -1;
+}
+
+static int netchannel_convert_skb(struct sk_buff *skb, struct unetchannel *unc)
+{
+	if (skb->pkt_type == PACKET_OTHERHOST)
+		return -1;
+
+	switch (ntohs(skb->protocol)) {
+		case ETH_P_IP:
+			return netchannel_convert_skb_ipv4(skb, unc);
+		case ETH_P_IPV6:
+			return netchannel_convert_skb_ipv6(skb, unc);
+		default:
+			return -1;
+	}
+}
+
+/*
+ * By design netchannels allow to "allocate" data
+ * not only from SLAB cache, but get it from mapped area
+ * or from VFS cache (requires process' context or preallocation).
+ */
+struct sk_buff *netchannel_alloc(struct unetchannel *unc, unsigned int header_size, 
+		unsigned int total_size, gfp_t gfp_mask)
+{
+	struct netchannel *nc;
+	struct netchannel_cache_head *bucket;
+	int err;
+	struct sk_buff *skb = NULL;
+	unsigned int size, pnum, i;
+
+	skb = alloc_skb(header_size, gfp_mask);
+	if (!skb)
+		return NULL;
+
+	rcu_read_lock();
+	bucket = netchannel_bucket(unc);
+	nc = netchannel_check_full(unc, bucket);
+	if (!nc) {
+		err = -ENODEV;
+		goto err_out_free_skb;
+	}
+
+	if (!nc->nc_alloc_page || !nc->nc_free_page) {
+		err = -EINVAL;
+		goto err_out_free_skb;
+	}
+
+	netchannel_get(nc);
+
+	size = total_size - header_size;
+	pnum = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+	for (i=0; i<pnum; ++i) {
+		unsigned int cs = min_t(unsigned int, PAGE_SIZE, size);
+		struct page *page;
+
+		page = nc->nc_alloc_page(cs);
+		if (!page)
+			break;
+		
+		skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 0, cs);
+		
+		skb->len	+= cs;
+		skb->data_len	+= cs;
+		skb->truesize	+= cs;
+
+		size -= cs;
+	}
+
+	if (i < pnum) {
+		pnum = i;
+		err = -ENOMEM;
+		goto err_out_free_frags;
+	}
+
+	rcu_read_unlock();
+
+	return skb;
+
+err_out_free_frags:
+	for (i=0; i<pnum; ++i) {
+		unsigned int cs = skb_shinfo(skb)->frags[i].size;
+		struct page *page = skb_shinfo(skb)->frags[i].page;
+		
+		nc->nc_free_page(page);
+
+		skb->len	-= cs;
+		skb->data_len	-= cs;
+		skb->truesize	-= cs;
+	}
+
+err_out_free_skb:
+	kfree_skb(skb);
+	return NULL;
+}
+
+int netchannel_recv(struct sk_buff *skb)
+{
+	struct netchannel *nc;
+	struct unetchannel unc;
+	struct netchannel_cache_head *bucket;
+	int err;
+
+	if (!netchannel_hash_table)
+		return -ENODEV;
+
+	rcu_read_lock();
+
+	err = netchannel_convert_skb(skb, &unc);
+	if (err)
+		goto unlock;
+
+	bucket = netchannel_bucket(&unc);
+	nc = netchannel_check_full(&unc, bucket);
+	if (!nc) {
+		err = -ENODEV;
+		goto unlock;
+	}
+
+	nc->hit++;
+#if 0
+	if (nc->qlen + skb->len > (1 << nc->unc.memory_limit_order)) {
+		kfree_skb(skb);
+		err = 0;
+		goto unlock;
+	}
+#endif
+	nc->qlen += skb->len;
+	skb_queue_tail(&nc->recv_queue, skb);
+	wake_up(&nc->wait);
+
+unlock:
+	rcu_read_unlock();
+	
+	return err;
+}
+
+static int netchannel_wait_for_packet(struct netchannel *nc, long *timeo_p)
+{
+	int error = 0;
+	DEFINE_WAIT(wait);
+
+	prepare_to_wait_exclusive(&nc->wait, &wait, TASK_INTERRUPTIBLE);
+
+	if (skb_queue_empty(&nc->recv_queue)) {
+		if (signal_pending(current))
+			goto interrupted;
+
+		*timeo_p = schedule_timeout(*timeo_p);
+	}
+out:
+	finish_wait(&nc->wait, &wait);
+	return error;
+interrupted:
+	error = (*timeo_p == MAX_SCHEDULE_TIMEOUT) ? -ERESTARTSYS : -EINTR;
+	goto out;
+}
+
+static struct sk_buff *netchannel_get_skb(struct netchannel *nc, unsigned int *timeout, int *error)
+{
+	struct sk_buff *skb = NULL;
+	long tm = *timeout;
+
+	*error = 0;
+
+	while (1) {
+		skb = skb_dequeue(&nc->recv_queue);
+		if (skb) {
+			nc->qlen -= skb->len;
+			break;
+		}
+
+		if (*timeout) {
+			*error = netchannel_wait_for_packet(nc, &tm);
+			if (*error) {
+				*timeout = tm;
+				break;
+			}
+			tm = *timeout;
+		} else {
+			*error = -EAGAIN;
+			break;
+		}
+	}
+
+	return skb;
+}
+
+static int netchannel_copy_to_user_tcp(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+	struct tcphdr *th;
+	int err = -ENODEV;
+	struct socket *sock;
+	struct sock *sk;
+	struct sk_buff *skb;
+	struct iovec iov;
+	struct msghdr msg;
+	unsigned flags = MSG_DONTWAIT;
+	unsigned int size = *len, read = 0, osize = *len;
+	unsigned int slen, process;
+
+	if (!nc->inode)
+		goto err_out;
+	sock = SOCKET_I(nc->inode);
+	if (!sock || !sock->sk)
+		goto err_out;
+
+	sk = sock->sk;
+
+	while (size) {
+		msg.msg_control=NULL;
+		msg.msg_controllen=0;
+		msg.msg_iovlen=1;
+		msg.msg_iov=&iov;
+		msg.msg_name=NULL;
+		msg.msg_namelen=0;
+		msg.msg_flags = flags;
+		iov.iov_len=size;
+		iov.iov_base=arg;
+
+		err = sock_recvmsg(sock, &msg, iov.iov_len, flags);
+
+		if (err > 0) {
+			size -= err;
+			read += err;
+
+			if (!size) {
+				err = 0;
+				break;
+			}
+		} else if (err && err != -EAGAIN)
+			break;
+
+		err = 0;
+		process = 0;
+		slen = 0;
+
+		while (slen < size) {
+			if (skb_queue_empty(&nc->recv_queue) && slen)
+				break;
+			skb = netchannel_get_skb(nc, timeout, &err);
+			if (!skb)
+				break;
+			skb->netchannel = 1;
+
+			__skb_pull(skb, skb->nh.iph->ihl*4);
+
+			skb->h.raw = skb->data;
+
+			th = skb->h.th;
+			TCP_SKB_CB(skb)->seq = ntohl(th->seq);
+			TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
+						    skb->len - th->doff * 4);
+			TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
+			TCP_SKB_CB(skb)->when	 = 0;
+			TCP_SKB_CB(skb)->flags	 = skb->nh.iph->tos;
+			TCP_SKB_CB(skb)->sacked	 = 0;
+
+			if (sk->sk_backlog_rcv) {
+				err = sk->sk_backlog_rcv(sk, skb);
+				if (err)
+					break;
+			}
+
+			slen += skb->len;
+		}
+	}
+
+	*len = read;
+
+	return err;
+
+err_out:
+	return err;
+}
+
+static int netchannel_copy_to_user(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+	unsigned int copied;
+	struct sk_buff *skb;
+	struct iovec to;
+	int err;
+
+	skb = netchannel_get_skb(nc, timeout, &err);
+	if (!skb)
+		return err;
+
+	to.iov_base = arg;
+	to.iov_len = *len;
+
+	copied = skb->len;
+	if (copied > *len)
+		copied = *len;
+
+	if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+		err = skb_copy_datagram_iovec(skb, 0, &to, copied);
+	} else {
+		err = skb_copy_and_csum_datagram_iovec(skb,0, &to);
+	}
+
+	*len = (err == 0)?copied:0;
+
+	kfree_skb(skb);
+
+	return err;
+}
+
+int netchannel_skb_copy_datagram(const struct sk_buff *skb, int offset,
+			    void *to, int len)
+{
+	int start = skb_headlen(skb);
+	int i, copy = start - offset;
+
+	/* Copy header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		memcpy(to, skb->data + offset, copy);
+
+		if ((len -= copy) == 0)
+			return 0;
+		offset += copy;
+		to += copy;
+	}
+
+	/* Copy paged appendix. Hmm... why does this look so complicated? */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		if ((copy = end - offset) > 0) {
+			u8  *vaddr;
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			struct page *page = frag->page;
+
+			if (copy > len)
+				copy = len;
+			vaddr = kmap(page);
+			memcpy(to, vaddr + frag->page_offset +
+					     offset - start, copy);
+			kunmap(page);
+			if (!(len -= copy))
+				return 0;
+			offset += copy;
+			to += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			if ((copy = end - offset) > 0) {
+				if (copy > len)
+					copy = len;
+				if (netchannel_skb_copy_datagram(list,
+							    offset - start,
+							    to, copy))
+					goto fault;
+				if ((len -= copy) == 0)
+					return 0;
+				offset += copy;
+				to += copy;
+			}
+			start = end;
+		}
+	}
+	if (!len)
+		return 0;
+
+fault:
+	return -EFAULT;
+}
+
+static int netchannel_copy_to_mem(struct netchannel *nc, unsigned int *timeout, unsigned int *len, void *arg)
+{
+	struct netchannel_mmap *m = nc->priv;
+	unsigned int copied, skb_offset = 0;
+	struct sk_buff *skb;
+	int err;
+
+	skb = netchannel_get_skb(nc, timeout, &err);
+	if (!skb)
+		return err;
+
+	copied = skb->len;
+
+	while (copied) {
+		int pnum = ((m->poff % PAGE_SIZE) % m->pnum);
+		struct page *page = m->page[pnum];
+		void *page_map, *ptr;
+		unsigned int sz, left;
+
+		left = PAGE_SIZE - (m->poff % (PAGE_SIZE - 1));
+		sz = min_t(unsigned int, left, copied);
+
+		if (!sz) {
+			err = -ENOSPC;
+			goto err_out;
+		}
+
+		page_map = kmap_atomic(page, KM_USER0);
+		if (!page_map) {
+			err = -ENOMEM;
+			goto err_out;
+		}
+		ptr = page_map + (m->poff % (PAGE_SIZE - 1));
+
+		err = netchannel_skb_copy_datagram(skb, skb_offset, ptr, sz);
+		if (err) {
+			kunmap_atomic(page_map, KM_USER0);
+			goto err_out;
+		}
+		kunmap_atomic(page_map, KM_USER0);
+
+		copied -= sz;
+		m->poff += sz;
+		skb_offset += sz;
+#if 1
+		if (m->poff >= PAGE_SIZE * m->pnum) {
+			//netchannel_dump_info_unc(&nc->unc, "rewind", nc->hit, 0);
+			m->poff = 0;
+		}
+#endif
+	}
+	*len = skb->len;
+
+	err = 0;
+
+err_out:
+	kfree_skb(skb);
+
+	return err;
+}
+
+static int netchannel_mmap_setup(struct netchannel *nc)
+{
+	struct netchannel_mmap *m;
+	unsigned int i, pnum;
+
+	pnum = (1 << (nc->unc.memory_limit_order - NETCHANNEL_MIN_ORDER));
+
+	m = kzalloc(sizeof(struct netchannel_mmap) + sizeof(struct page *) * pnum, GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	m->page = (struct page **)(m + 1);
+	m->pnum = pnum;
+
+	for (i=0; i<pnum; ++i) {
+		m->page[i] = alloc_page(GFP_KERNEL);
+		if (!m->page[i])
+			break;
+	}
+
+	if (i < pnum) {
+		pnum = i;
+		goto err_out_free;
+	}
+
+	nc->priv = m;
+
+	switch (nc->unc.proto) {
+		case IPPROTO_TCP:
+			nc->nc_read_data = &netchannel_copy_to_user_tcp;
+			break;
+		case IPPROTO_UDP:
+		default:
+			nc->nc_read_data = &netchannel_copy_to_mem;
+			break;
+	}
+
+	return 0;
+
+err_out_free:
+	for (i=0; i<pnum; ++i)
+		__free_page(m->page[i]);
+
+	kfree(m);
+
+	return -ENOMEM;
+	
+}
+
+static int netchannel_copy_user_setup(struct netchannel *nc)
+{
+	int ret = 0;
+	
+	switch (nc->unc.proto) {
+		case IPPROTO_UDP:
+			nc->nc_read_data = &netchannel_copy_to_user;
+			break;
+		case IPPROTO_TCP:
+			nc->nc_read_data = &netchannel_copy_to_user_tcp;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int netchannel_setup(struct netchannel *nc)
+{
+	int ret = 0;
+
+	if (nc->unc.memory_limit_order > NETCHANNEL_MAX_ORDER)
+		nc->unc.memory_limit_order = NETCHANNEL_MAX_ORDER;
+
+	if (nc->unc.memory_limit_order < NETCHANNEL_MIN_ORDER)
+		nc->unc.memory_limit_order = NETCHANNEL_MIN_ORDER;
+	
+	switch (nc->unc.type) {
+		case NETCHANNEL_COPY_USER:
+			ret = netchannel_copy_user_setup(nc);
+			break;
+		case NETCHANNEL_MMAP:
+			ret = netchannel_mmap_setup(nc);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int netchannel_bind(struct unetchannel_control *ctl)
+{
+	struct netchannel *nc;
+	int err = -EINVAL, fput_needed;
+	struct netchannel_cache_head *bucket;
+	struct file *file;
+	struct inode *inode;
+
+	file = fget_light(ctl->fd, &fput_needed);
+	if (!file)
+		goto err_out_exit;
+
+	inode = igrab(file->f_dentry->d_inode);
+	if (!inode)
+		goto err_out_fput;
+
+	bucket = netchannel_bucket(&ctl->unc);
+	
+	mutex_lock(&bucket->mutex);
+	
+	nc = netchannel_check_full(&ctl->unc, bucket);
+	if (!nc) {
+		err = -ENODEV;
+		goto err_out_unlock;
+	}
+
+	nc->inode = inode;
+
+	fput_light(file, fput_needed);
+	mutex_unlock(&bucket->mutex);
+
+	return 0;
+
+err_out_unlock:
+	mutex_unlock(&bucket->mutex);
+err_out_fput:
+	fput_light(file, fput_needed);
+err_out_exit:
+	return err;
+}
+
+static int netchannel_create(struct unetchannel *unc)
+{
+	struct netchannel *nc;
+	int err = -ENOMEM;
+	struct netchannel_cache_head *bucket;
+	
+	nc = kmem_cache_alloc(netchannel_cache, GFP_KERNEL);
+	if (!nc)
+		return -ENOMEM;
+
+	memset(nc, 0, sizeof(struct netchannel));
+	
+	nc->hit = 0;
+	skb_queue_head_init(&nc->recv_queue);
+	init_waitqueue_head(&nc->wait);
+	atomic_set(&nc->refcnt, 1);
+	memcpy(&nc->unc, unc, sizeof(struct unetchannel));
+
+	err = netchannel_setup(nc);
+	if (err)
+		goto err_out_free;
+	
+	bucket = netchannel_bucket(unc);
+	
+	mutex_lock(&bucket->mutex);
+	
+	if (netchannel_check_full(unc, bucket)) {
+		err = -EEXIST;
+		goto err_out_unlock;
+	}
+
+	hlist_add_head_rcu(&nc->node, &bucket->head);
+	err = 0;
+
+	mutex_unlock(&bucket->mutex);
+	
+	netchannel_dump_info_unc(unc, "create", 0, err);
+
+	return err;
+
+err_out_unlock:
+	mutex_unlock(&bucket->mutex);
+
+	netchannel_cleanup(nc);
+
+err_out_free:
+	kmem_cache_free(netchannel_cache, nc);
+
+	return err;
+}
+
+static int netchannel_remove(struct unetchannel *unc)
+{
+	struct netchannel *nc;
+	int err = -ENODEV;
+	struct netchannel_cache_head *bucket;
+	unsigned long hit = 0;
+	
+	if (!netchannel_hash_table)
+		return -ENODEV;
+	
+	bucket = netchannel_bucket(unc);
+
+	mutex_lock(&bucket->mutex);
+
+	nc = netchannel_check_full(unc, bucket);
+	if (!nc)
+		nc = netchannel_check_dest(unc, bucket);
+
+	if (!nc)
+		goto out_unlock;
+	
+	hlist_del_rcu(&nc->node);
+	hit = nc->hit;
+	
+	if (nc->inode) {
+		iput(nc->inode);
+		nc->inode = NULL;
+	}
+	
+	netchannel_put(nc);
+	err = 0;
+
+out_unlock:
+	mutex_unlock(&bucket->mutex);
+	netchannel_dump_info_unc(unc, "remove", hit, err);
+	return err;
+}
+
+static int netchannel_recv_data(struct unetchannel_control *ctl, void __user *data)
+{
+	int ret = -ENODEV;
+	struct netchannel_cache_head *bucket;
+	struct netchannel *nc;
+	
+	bucket = netchannel_bucket(&ctl->unc);
+
+	mutex_lock(&bucket->mutex);
+
+	nc = netchannel_check_full(&ctl->unc, bucket);
+	if (!nc)
+		nc = netchannel_check_dest(&ctl->unc, bucket);
+
+	if (!nc)
+		goto err_out_unlock;
+
+	netchannel_get(nc);
+	mutex_unlock(&bucket->mutex);
+
+	ret = nc->nc_read_data(nc, &ctl->timeout, &ctl->len, data);
+	
+	netchannel_put(nc);
+	return ret;
+
+err_out_unlock:
+	mutex_unlock(&bucket->mutex);
+	return ret;
+}
+
+static int netchannel_dump_info(struct unetchannel *unc)
+{
+	struct netchannel_cache_head *bucket;
+	struct netchannel *nc;
+	char *ncs = "none";
+	unsigned long hit = 0;
+	int err;
+	
+	bucket = netchannel_bucket(unc);
+
+	mutex_lock(&bucket->mutex);
+	nc = netchannel_check_full(unc, bucket);
+	if (!nc) {
+		nc = netchannel_check_dest(unc, bucket);
+		if (nc)
+			ncs = "dest";
+	} else 
+		ncs = "full";
+	if (nc)
+		hit = nc->hit;
+	mutex_unlock(&bucket->mutex);
+	err = (nc)?0:-ENODEV;
+
+	netchannel_dump_info_unc(unc, ncs, hit, err);
+
+	return err;
+}
+
+asmlinkage long sys_netchannel_control(void __user *arg)
+{
+	struct unetchannel_control ctl;
+	int ret;
+
+	if (!netchannel_hash_table)
+		return -ENODEV;
+
+	if (copy_from_user(&ctl, arg, sizeof(struct unetchannel_control)))
+		return -ERESTARTSYS;
+
+	switch (ctl.cmd) {
+		case NETCHANNEL_CREATE:
+			ret = netchannel_create(&ctl.unc);
+			break;
+		case NETCHANNEL_BIND:
+			ret = netchannel_bind(&ctl);
+			break;
+		case NETCHANNEL_REMOVE:
+			ret = netchannel_remove(&ctl.unc);
+			break;
+		case NETCHANNEL_READ:
+			ret = netchannel_recv_data(&ctl, arg + sizeof(struct unetchannel_control));
+			break;
+		case NETCHANNEL_DUMP:
+			ret = netchannel_dump_info(&ctl.unc);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+	
+	if (copy_to_user(arg, &ctl, sizeof(struct unetchannel_control)))
+		return -ERESTARTSYS;
+
+	return ret;
+}
+
+static inline void netchannel_dump_addr(struct in_ifaddr *ifa, char *str)
+{
+	printk("netchannel: %s %u.%u.%u.%u/%u.%u.%u.%u\n", str, NIPQUAD(ifa->ifa_local), NIPQUAD(ifa->ifa_mask));
+}
+
+static int netchannel_inetaddr_notifier_call(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct in_ifaddr *ifa = ptr;
+
+	switch (event) {
+		case NETDEV_UP:
+			netchannel_dump_addr(ifa, "add");
+			break;
+		case NETDEV_DOWN:
+			netchannel_dump_addr(ifa, "del");
+			break;
+		default:
+			netchannel_dump_addr(ifa, "unk");
+			break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+#ifdef CONFIG_IPV6
+static int netchannel_inet6addr_notifier_call(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct inet6_ifaddr *ifa = ptr;
+
+	printk("netchannel: inet6 event=%lx, ifa=%p.\n", event, ifa);
+	return NOTIFY_DONE;
+}
+#endif
+
+static int __init netchannel_init(void)
+{
+	unsigned int i, j, size;
+	int err = -ENOMEM;
+
+	size = (1 << netchannel_hash_order);
+
+	netchannel_hash_table = kzalloc(size * sizeof(void *), GFP_KERNEL);
+	if (!netchannel_hash_table)
+		goto err_out_exit;
+
+	for (i=0; i<size; ++i) {
+		struct netchannel_cache_head **col;
+
+		col = kzalloc(size * sizeof(void *), GFP_KERNEL);
+		if (!col)
+			break;
+		
+		for (j=0; j<size; ++j) {
+			struct netchannel_cache_head *head;
+
+			head = kzalloc(sizeof(struct netchannel_cache_head), GFP_KERNEL);
+			if (!head)
+				break;
+
+			INIT_HLIST_HEAD(&head->head);
+			mutex_init(&head->mutex);
+
+			col[j] = head;
+		}
+		
+		if (j<size && j>0) {
+			while (j >= 0)
+				kfree(col[j--]);
+			kfree(col);
+			break;
+		}
+
+		netchannel_hash_table[i] = col;
+	}
+
+	if (i<size) {
+		size = i;
+		goto err_out_free;
+	}
+
+	netchannel_cache = kmem_cache_create("netchannel", sizeof(struct netchannel), 0, 0,
+			NULL, NULL);
+	if (!netchannel_cache)
+		goto err_out_free;
+
+	register_inetaddr_notifier(&netchannel_inetaddr_notifier);
+#ifdef CONFIG_IPV6
+	register_inet6addr_notifier(&netchannel_inet6addr_notifier);
+#endif
+
+	printk("netchannel: Created %u order two-dimensional hash table.\n", 
+			netchannel_hash_order);
+
+	return 0;
+
+err_out_free:
+	for (i=0; i<size; ++i) {
+		for (j=0; j<(1 << netchannel_hash_order); ++j)
+			kfree(netchannel_hash_table[i][j]);
+		kfree(netchannel_hash_table[i]);
+	}
+	kfree(netchannel_hash_table);
+err_out_exit:
+	
+	printk("netchannel: Failed to create %u order two-dimensional hash table.\n", 
+			netchannel_hash_order);
+	return err;
+}
+
+static void __exit netchannel_exit(void)
+{
+	unsigned int i, j;
+
+	unregister_inetaddr_notifier(&netchannel_inetaddr_notifier);
+#ifdef CONFIG_IPV6
+	unregister_inet6addr_notifier(&netchannel_inet6addr_notifier);
+#endif
+	kmem_cache_destroy(netchannel_cache);
+
+	for (i=0; i<(1 << netchannel_hash_order); ++i) {
+		for (j=0; j<(1 << netchannel_hash_order); ++j)
+			kfree(netchannel_hash_table[i][j]);
+		kfree(netchannel_hash_table[i]);
+	}
+	kfree(netchannel_hash_table);
+}
+
+late_initcall(netchannel_init);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fb3770f..f979fd6 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -437,6 +437,7 @@ struct sk_buff *skb_clone(struct sk_buff
 	C(pkt_type);
 	C(ip_summed);
 	C(priority);
+	C(netchannel);
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	C(ipvs_property);
 #endif
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 672950e..eb2dc12 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -727,7 +727,10 @@ int tcp_v4_conn_request(struct sock *sk,
 #endif
 
 	/* Never answer to SYNs send to broadcast or multicast */
-	if (((struct rtable *)skb->dst)->rt_flags &
+	if (!skb->dst) {
+		if (MULTICAST(daddr))
+			goto drop;
+	} else if (((struct rtable *)skb->dst)->rt_flags &
 	    (RTCF_BROADCAST | RTCF_MULTICAST))
 		goto drop;
 
@@ -924,15 +927,21 @@ static struct sock *tcp_v4_hnd_req(struc
 	struct iphdr *iph = skb->nh.iph;
 	struct sock *nsk;
 	struct request_sock **prev;
+	int iif;
 	/* Find possible connection requests. */
 	struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
 						       iph->saddr, iph->daddr);
 	if (req)
 		return tcp_check_req(sk, skb, req, prev);
 
+	if (!skb->dst)
+		iif = 0;
+	else
+		iif = inet_iif(skb);
+
 	nsk = __inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
 					th->source, skb->nh.iph->daddr,
-					ntohs(th->dest), inet_iif(skb));
+					ntohs(th->dest), iif);
 
 	if (nsk) {
 		if (nsk->sk_state != TCP_TIME_WAIT) {
-- 
	Evgeniy Polyakov



-- 
	Evgeniy Polyakov

^ permalink raw reply related

* Re: netif_tx_disable and lockless TX
From: Robert Olsson @ 2006-06-02 10:46 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Robert Olsson, hadi, Herbert Xu, netdev, jgarzik, mchan,
	David Miller, Andi Kleen
In-Reply-To: <447FAFAD.9000503@osdl.org>


Stephen Hemminger writes:

 > I also noticed that you really don't save much by doing TX cleaning at 
 > hardirq, because in hardirq you need to do dev_kfree_irq and that causes 
 > a softirq (for the routing case where users=1). So when routing it 
 > doesn't make much difference, both methods cause the softirq delayed 
 > processing to be invoked. For locally generated packets which are 
 > cloned, the hardirq will drop the ref count, and that is faster than 
 > doing the whole softirq round trip.

 Right. Also the other way around, repeated ->poll can avoid TX hardirq's.

 Cheers.
						--ro

^ permalink raw reply

* new driver for IBM ethernet chip
From: Christoph Raisch @ 2006-06-02 11:02 UTC (permalink / raw)
  To: netdev; +Cc: Marcus Eder, Jan-Bernd Themann

We're currently developing a new Ethernet device driver for a 10G IBM chip
for System p. (ppc64)

A later version of the driver should end up in mainline kernel.
How should we proceed to get first comments by the community?
Either post this code as a patch to netdev or
put a full tarball on for example sourceforge?


Gruss / Regards . . . Christoph Raisch

christoph raisch, HCAD teamlead, IODF2 (d/3627), ibm boeblingen lab,
phone: (+49/0)7031-16 4584,  fax: -16 2042, loc: 71032-05-003, internet:
raisch@de.ibm.com


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox