* [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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox