Netdev List
 help / color / mirror / Atom feed
* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Herbert Xu @ 2005-05-17 22:11 UTC (permalink / raw)
  To: David S. Miller; +Cc: akepner, netdev
In-Reply-To: <20050517.104947.112621738.davem@davemloft.net>

David S. Miller <davem@davemloft.net> wrote:
>
> Decreasing ipfrag_time is also not an option, because then

Here is a possible solution to this:

Instead of measuring the distance using time, let's measure it
in terms of packet counts.  So every time we receive a fragmented
packet, we find all waiting fragments with the same src/dst pair.
If the id is identical we perform reassembly, if it isn't we increase
a counter in that fragment.  If the counter exceeds a threshold,
we drop the fragment.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Arthur Kepner @ 2005-05-17 22:06 UTC (permalink / raw)
  To: Rick Jones; +Cc: netdev, netdev-bounce
In-Reply-To: <428A613F.1020303@hp.com>


On Tue, 17 May 2005, Rick Jones wrote:

> ....
> or an added heuristic of "if have reassembled N datagrams for the same
> source/dest/protocol tuple with ID's "larger" than 'this one' since it has
> arrived, we are probably going to wrap so might as well drop 'this one'"  for
> some judicious and magical selection of N that may be a decent predictor of
> wrap on top of some existing reassembly timout.
> ....

How do you define "larger" in this case? A sender is free to choose 
any ID - they can't be assumed to be montonic, for sure. 

--
Arthur

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Rick Jones @ 2005-05-17 21:25 UTC (permalink / raw)
  To: netdev; +Cc: netdev-bounce
In-Reply-To: <20050517.140245.71090021.davem@davemloft.net>

this may be drifting tooo much, but it seems the issue of deciding when to 
give-up on reassembly of an IP datagram is similar to the issues that neterion 
are going to be going-through creating their "LRO" (Large Receive Offload) 
solution, albeit the potential consequences of a bad decision are rather different.

both seek to know when it is unlikely that no more frames/fragments will arrive.

just how much extra overhead would there be to track the interarrival time of ip 
datagram fragments and would that allow someone to make a guess as to how long 
to reasonably wait for all the fragments to arrive? (or did I miss that being 
shot-down already?)

or an added heuristic of "if have reassembled N datagrams for the same 
source/dest/protocol tuple with ID's "larger" than 'this one' since it has 
arrived, we are probably going to wrap so might as well drop 'this one'"  for 
some judicious and magical selection of N that may be a decent predictor of wrap 
on top of some existing reassembly timout.

rick jones

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: David S. Miller @ 2005-05-17 21:24 UTC (permalink / raw)
  To: ak; +Cc: dlstevens, akepner, jheffner, netdev, netdev-bounce
In-Reply-To: <20050517211300.GB79960@muc.de>

From: Andi Kleen <ak@muc.de>
Date: 17 May 2005 23:13:01 +0200,Tue, 17 May 2005 23:13:00 +0200

> On Tue, May 17, 2005 at 02:02:45PM -0700, David S. Miller wrote:
> > From: Andi Kleen <ak@muc.de>
> > Date: 17 May 2005 22:27:30 +0200,Tue, 17 May 2005 22:27:30 +0200
> > 
> > > But it's not clear such a hack would be worth it anyways. 
> > > If anything it would be probably better to let mountd set the RTTs, e.g. 
> > > implicitely with MSG_CONFIRM (I hope it is using it these days ...) 
> > 
> > I think we should implement a solution that goes beyond
> > the confines of NFS.
> 
> Nothing in MSG_CONFIRM is NFS specific.

I'm referring to mountd.

^ permalink raw reply

* Re: [PATCH 11/12] orinoco: monitor mode support
From: Francois Romieu @ 2005-05-17 21:22 UTC (permalink / raw)
  To: Pavel Roskin; +Cc: Christoph Hellwig, jgarzik, hermes, netdev
In-Reply-To: <1116358994.5534.2.camel@dv.roinet.com>

Pavel Roskin <proski@gnu.org> :
> On Sat, 2005-05-14 at 19:39 +0200, Francois Romieu wrote:
> > > + drop:
> > > +	stats->rx_errors++;
> > > +	stats->rx_dropped++;
> > > +}
> > 
> > -> leak (skb).
> 
> Indeed.  Thank you!  Please apply this on top of the original patches:
> 
> Signed-off-by: Pavel Roskin <proski@gnu.org>
> 
> --- orinoco.c
> +++ orinoco.c
> @@ -1180,7 +1180,7 @@ static void orinoco_rx_monitor(struct ne
>  	u16 fc;
>  	int err;
>  	int len;
> -	struct sk_buff *skb;
> +	struct sk_buff *skb = NULL;
>  	struct orinoco_private *priv = netdev_priv(dev);
>  	struct net_device_stats *stats = &priv->stats;
>  	hermes_t *hw = &priv->hw;
> @@ -1268,6 +1268,8 @@ static void orinoco_rx_monitor(struct ne
>   drop:
>  	stats->rx_errors++;
>  	stats->rx_dropped++;
> +	if (skb)
> +		dev_kfree_skb_irq(skb);
>  }
>  
>  static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
> 
> 

I am not fond of unneeded/hidden state variable. What about:

+       /* sanity check the length */
+       if (datalen > IEEE80211_DATA_LEN + 12) {
+               printk(KERN_DEBUG "%s: oversized monitor frame, "
+                      "data length = %d\n", dev->name, datalen);
+               err = -EIO;
+               goto drop;
                ^^^^^^^^^^ -> let's replace by 'goto update_stats;'
And turn:
+   drop:
+       stats->rx_errors++;
+       stats->rx_dropped++;

into:

+   drop:
+       dev_kfree_skb_irq(skb);     
+   update_stats:
+       stats->rx_errors++;
+       stats->rx_dropped++;

This way 'goto drop' really drops and the code does not issue a 'goto drop'
when it actually want to update the stats.

--
Ueimor

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Andi Kleen @ 2005-05-17 21:13 UTC (permalink / raw)
  To: David S. Miller; +Cc: dlstevens, akepner, jheffner, netdev, netdev-bounce
In-Reply-To: <20050517.140245.71090021.davem@davemloft.net>

On Tue, May 17, 2005 at 02:02:45PM -0700, David S. Miller wrote:
> From: Andi Kleen <ak@muc.de>
> Date: 17 May 2005 22:27:30 +0200,Tue, 17 May 2005 22:27:30 +0200
> 
> > But it's not clear such a hack would be worth it anyways. 
> > If anything it would be probably better to let mountd set the RTTs, e.g. 
> > implicitely with MSG_CONFIRM (I hope it is using it these days ...) 
> 
> I think we should implement a solution that goes beyond
> the confines of NFS.

Nothing in MSG_CONFIRM is NFS specific.

-Andi

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: David S. Miller @ 2005-05-17 21:02 UTC (permalink / raw)
  To: ak; +Cc: dlstevens, akepner, jheffner, netdev, netdev-bounce
In-Reply-To: <20050517202730.GA79960@muc.de>

From: Andi Kleen <ak@muc.de>
Date: 17 May 2005 22:27:30 +0200,Tue, 17 May 2005 22:27:30 +0200

> But it's not clear such a hack would be worth it anyways. 
> If anything it would be probably better to let mountd set the RTTs, e.g. 
> implicitely with MSG_CONFIRM (I hope it is using it these days ...) 

I think we should implement a solution that goes beyond
the confines of NFS.

^ permalink raw reply

* Re: [patch linux-2.6.12-rc3-mm3 1/7] r8169: de-obfuscate supported PCI ID
From: Francois Romieu @ 2005-05-17 20:48 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew Morton, netdev
In-Reply-To: <4287C9D6.1060004@pobox.com>

Jeff Garzik <jgarzik@pobox.com> :
> All seven look OK, but it failed on the first patch:
> 
> [jgarzik@pretzel netdev-2.6]$ dotest /g/tmp/mbox
> 
> Applying 'r8169: de-obfuscate supported PCI ID'
> 
> patching file drivers/net/r8169.c
> Hunk #1 FAILED at 174.
> 1 out of 1 hunk FAILED -- saving rejects to file drivers/net/r8169.c.rej

Yes. In the meantime, -mm was applied:
[patch 2.6.12-rc2-mm3 1/1] r8169: new PCI id

Should I send a serie of patches against
126fa4b9ca5d9d7cb7d46f779ad3bd3631ca387c to update it to r8169-mm-latest ?

--
Ueimor

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Thomas Graf @ 2005-05-17 20:48 UTC (permalink / raw)
  To: David S. Miller; +Cc: jheffner, ak, netdev, akepner
In-Reply-To: <20050517.120950.74749758.davem@davemloft.net>

* David S. Miller <20050517.120950.74749758.davem@davemloft.net> 2005-05-17 12:09
> From: John Heffner <jheffner@psc.edu>
> Date: Tue, 17 May 2005 14:57:38 -0400
> 
> > It would be better still to have a per-route packet reassembly timeout in 
> > milliseconds.
> 
> I agree.  And if we can setup the infrastructure such that the
> drivers can indicate the speed of the link they are communicating
> on, then we can set sane default values on the automatically
> created subnet routes.

I think we have two separate issues to resolve, first we need
to figure out a way to state the probability of a id wrap, this
can be a very simple pps rate estimator on the driver statistics
for hardware interfaces and something more tricky for virtual
interfaces such as found in xen. I think the link speed is not
reliable enough for this.

The second issue covers the actual defeat of the wraps, we have
to differ between the rare but possible case for long delayed
fragments and short delayed reorderings as caused by SMP. A
combination of both short and long delayed reorderings rarely
happens in practice and if so that's the bigger problem anyway.
The above probability can be used to distinguish these cases
and be more specific. SMP caused fragments have a very local
distribution and thus the window for accepted ids can be smaller
than the one for a long delayed fragment session. So maybe we
can use the above probability as a factor to calculate a window
of accepted ids.

^ permalink raw reply

* Re: Qdisc requeue should be void?
From: Patrick McHardy @ 2005-05-17 20:47 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Jamal Hadi Salim, lartc
In-Reply-To: <20050513105754.2e7cc243@dxpl.pdx.osdl.net>

Stephen Hemminger wrote:
> There is an design problem with the qdisc interface that causes qlen related bugs
> in netem, tbf, and other qdisc's that peek at the top of the queue. The problem is
> that requeue needs to be called from the dequeue function but requeue can fail.
> If requeue fails, then the calling qdisc can not properly handle the error.  If it
> returns NULL, then the parent's expectation about qlen gets messed up.
> 
> Example:
> 
> 	prio (qlen = 1)
> 		skb = netem dequeue 
> 			skb = htb dequeue 
> 			... decides not to send this skb now
> 			htp requeue(skb) fails
> 				?? what now 
> 				--netem.qlen // := 0
> 				return NULL
> 		 skb is NULL
> 
> at this point prio qlen is 1 but underlying queue's are empty.
> 
> My proposal is to require requeue to always succeed and change it to be
> void instead of returning int.

Perhaps we should add a ->peek() operation which guarantees that the
next dequeued packet is the one peeked at. This would also help with
a second problem resulting from requeueing in at least TBF and HFSC.
TBF looks at a packet and if it can't be sent immediately calculates
the delay from the packet's length. HFSC does the same to calculate
the deadline for a class. Both assume the next packet dequeued from
the underlying qdisc is the one requeued, which is only true with
non-reordering qdiscs. Adding a peek-operation increases the worst-case
delay by one maximum sized packet transmission time, but otherwise
these qdiscs can't make proper use of reordering qdiscs like SFQ
at all.

Regards
Patrick

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: John Heffner @ 2005-05-17 20:29 UTC (permalink / raw)
  To: David Stevens; +Cc: Andi Kleen, akepner, David S. Miller, netdev
In-Reply-To: <OF0221F508.AD091D99-ON88257004.006D0C52-88257004.006D8293@us.ibm.com>

On Tuesday 17 May 2005 03:56 pm, David Stevens wrote:
> Dave,
>         Shouldn't that be an estimator on the destination RTT? Or is that

Unfortunately, it's not the RTT that matters, but link speed.
You could probably do some heuristics on this, but I don't know if it's worth 
the effort.

IMO, high-rate applications which rely on IP fragmentation and a 16-bit ones 
complement for data integrity are broken, and a band-aid style workaround for 
them is probably good enough.  As long as it's not inflicted on the rest of 
us. :)

  -John

^ permalink raw reply

* [PATCH 2/2] Resend: LSM-IPSec Networking Hooks
From: jaegert @ 2005-05-17 20:27 UTC (permalink / raw)
  To: netdev, chrisw; +Cc: jaegert, serue, latten, sds, jmorris


This patch series implements per packet access control via the
extension of the Linux Security Modules (LSM) interface by hooks in
the XFRM and pfkey subsystems that leverage IPSec security
associations to label packets.  Extensions to the SELinux LSM are
included that leverage the patch for this purpose.

This patch implements the changes necessary to the SELinux LSM to
create, deallocate, and use security contexts for policies
(xfrm_policy) and security associations (xfrm_state) that enable
control of a socket's ability to send and receive packets.

Patch purpose:

The patch is designed to enable the SELinux LSM to implement access
control on individual packets based on the strongly authenticated
IPSec security association.  Such access controls augment the existing
ones in SELinux based on network interface and IP address.  The former
are very coarse-grained, and the latter can be spoofed.  By using
IPSec, the SELinux can control access to remote hosts based on
cryptographic keys generated using the IPSec mechanism.  This enables
access control on a per-machine basis or per-application if the remote
machine is running the same mechanism and trusted to enforce the
access control policy.

Patch design approach:

The patch's main function is to authorize a socket's access to a IPSec
policy based on their security contexts.  Since the communication is
implemented by a security association, the patch ensures that the
security association's negotiated and used have the same security
context.  The patch enables allocation and deallocation of such
security contexts for policies and security associations.  It also
enables copying of the security context when policies are cloned.
Lastly, the patch ensures that packets that are sent without using a
IPSec security assocation with a security context are allowed to be
sent in that manner.  

A presentation available at
www.selinux-symposium.org/2005/presentations/session2/2-3-jaeger.pdf
from the SELinux symposium describes the overall approach.

Patch implementation details: 

The function which authorizes a socket to perform a requested
operation (send/receive) on a IPSec policy (xfrm_policy) is
selinux_xfrm_policy_lookup.  The Netfilter and rcv_skb hooks ensure
that if a IPSec SA with a securit y association has not been used,
then the socket is allowed to send or receive the packet,
respectively.

The patch implements SELinux function for allocating security contexts
when policies (xfrm_policy) are created via the pfkey or xfrm_user
interfaces via selinux_xfrm_policy_alloc.  When a security association
is built, SELinux allocates the security context designated by the
XFRM subsystem which is based on that of the authorized policy via
selinux_xfrm_state_alloc.

When a xfrm_policy is cloned, the security context of that policy, if
any, is copied to the clone via selinux_xfrm_policy_clone.

When a xfrm_policy or xfrm_state is freed, its security context, if
any is also freed at selinux_xfrm_policy_free or
selinux_xfrm_state_free.

Testing:

The SELinux authorization function is tested using ipsec-tools.  We
created policies and security associations with particular security
contexts and added SELinux access control policy entries to verify the
authorization decision.  We also made sure that packets for which no
security context was supplied (which either did or did not use
security associations) were authorized using an unlabelled context.


---

 security/selinux/Makefile           |    2 
 security/selinux/hooks.c            |   20 +
 security/selinux/include/nethooks.h |    8 
 security/selinux/nethooks.c         |  428 ++++++++++++++++++++++++++++++++++++
 4 files changed, 457 insertions(+), 1 deletion(-)

diff -puN security/selinux/hooks.c~lsm-selinux-nethooks security/selinux/hooks.c
--- linux-2.6.12-rc4-nethooks/security/selinux/hooks.c~lsm-selinux-nethooks	2005-05-13 13:15:47.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/hooks.c	2005-05-13 13:15:47.000000000 -0400
@@ -72,6 +72,7 @@
 #include "avc.h"
 #include "objsec.h"
 #include "netif.h"
+#include "nethooks.h"
 
 #define XATTR_SELINUX_SUFFIX "selinux"
 #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
@@ -3350,6 +3351,10 @@ static int selinux_socket_sock_rcv_skb(s
 		err = avc_has_perm(sock_sid, port_sid,
 				   sock_class, recv_perm, &ad);
 	}
+
+	if (!err)
+		err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+
 out:	
 	return err;
 }
@@ -3537,6 +3542,11 @@ static unsigned int selinux_ip_postroute
 		                   send_perm, &ad) ? NF_DROP : NF_ACCEPT;
 	}
 
+	if (err != NF_ACCEPT)
+		goto out;
+
+	err = selinux_xfrm_postroute_last(isec->sid, skb);
+
 out:
 	return err;
 }
@@ -4389,6 +4399,15 @@ static struct security_operations selinu
 	.sk_alloc_security =		selinux_sk_alloc_security,
 	.sk_free_security =		selinux_sk_free_security,
 #endif
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+	.xfrm_policy_alloc_security =	selinux_xfrm_policy_alloc,
+	.xfrm_policy_clone_security =	selinux_xfrm_policy_clone,
+	.xfrm_policy_free_security =	selinux_xfrm_policy_free,
+	.xfrm_state_alloc_security =	selinux_xfrm_state_alloc,
+	.xfrm_state_free_security =	selinux_xfrm_state_free,
+	.xfrm_policy_lookup =	        selinux_xfrm_policy_lookup,
+#endif
 };
 
 static __init int selinux_init(void)
@@ -4499,6 +4518,7 @@ static int __init selinux_nf_ip_init(voi
 		panic("SELinux: nf_register_hook for IPv6: error %d\n", err);
 
 #endif	/* IPV6 */
+
 out:
 	return err;
 }
diff -puN /dev/null security/selinux/include/nethooks.h
--- /dev/null	2004-02-23 16:02:56.000000000 -0500
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/include/nethooks.h	2005-05-13 13:15:47.000000000 -0400
@@ -0,0 +1,8 @@
+int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx);
+int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
+void selinux_xfrm_policy_free(struct xfrm_policy *xp);
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx);
+void selinux_xfrm_state_free(struct xfrm_state *x);
+int selinux_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir);
+int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb);
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb);
diff -puN security/selinux/Makefile~lsm-selinux-nethooks security/selinux/Makefile
--- linux-2.6.12-rc4-nethooks/security/selinux/Makefile~lsm-selinux-nethooks	2005-05-13 13:15:47.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/Makefile	2005-05-13 13:15:47.000000000 -0400
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
 
-selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o
+selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o nethooks.o
 
 selinux-$(CONFIG_SECURITY_NETWORK) += netif.o
 
diff -puN /dev/null security/selinux/nethooks.c
--- /dev/null	2004-02-23 16:02:56.000000000 -0500
+++ linux-2.6.12-rc4-nethooks-root/security/selinux/nethooks.c	2005-05-16 14:28:25.000000000 -0400
@@ -0,0 +1,428 @@
+/*
+ * USAGE:
+ * NOTES:
+ *   1. Make sure to enable the following options in your kernel config:
+ *	CONFIG_SECURITY=y
+ *	CONFIG_SECURITY_NETWORK=y
+ *	CONFIG_SECURITY_NETWORK_XFRM=y
+ *	CONFIG_SECURITY_SELINUX=m/y
+ * ISSUES:
+ *   1. Caching packets, so they are not dropped during negotiation
+ *   2. Emulating a reasonable SO_PEERSEC across machines
+ *   3. Testing sk_policy setting with context
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/xfrm.h>
+#include <net/xfrm.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+#include <asm/semaphore.h>
+
+#include "nethooks.h"
+#include "avc.h"
+#include "objsec.h"
+
+/**************************************************************
+ *
+ * defines
+ *
+ **************************************************************/
+
+#define DEBUG 0
+
+/**************************************************************
+ *
+ * structures
+ *
+ **************************************************************/
+
+/**************************************************************
+ *
+ * globals
+ *
+ **************************************************************/
+
+/**************************************************************
+ *
+ * macros/inlines
+ *
+ **************************************************************/
+
+#define nethooks_debug(fmt, args...) {if (DEBUG) printk(KERN_NOTICE fmt,## args);}
+
+/*
+ * Extract the security blob from the sock (it's actually on the socket)
+ */
+static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
+{
+	if (!sk->sk_socket) {
+		nethooks_debug("%s: no socket on this sock (!?)\n",
+			       __FUNCTION__);
+		return (struct inode_security_struct *) NULL;
+	}
+
+	return SOCK_INODE(sk->sk_socket)->i_security;
+}
+
+/*
+ * Returns true if the xfrm contains a security blob for SELinux
+ */
+static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_state_security(x);
+
+	return (xfrm_ctx &&
+		(xfrm_ctx->ctx_doi == XFRM_SC_DOI_LSM) &&
+		(xfrm_ctx->ctx_alg == XFRM_SC_ALG_SELINUX));
+}
+
+/**************************************************************
+ *
+ * LSM
+ *
+ **************************************************************/
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+/*
+ * LSM hook implementation that authorizes that a socket can be used
+ * with the corresponding xfrm_policy selector and direction.
+ */
+
+int selinux_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+	int rc = 0;
+	struct inode_security_struct *isec = NULL;
+	u32 sock_sid, sel_sid = SECINITSID_UNLABELED;
+
+	nethooks_debug("%s: authorize\n", __FUNCTION__);
+
+	if (!sk) {
+                /* no sock to send -- e.g., icmp reply */
+		/* authorize as kernel packet */
+		if (fl && fl->proto == IPPROTO_ICMP) {
+			nethooks_debug("%s: ICMP case\n",
+				       __FUNCTION__);
+			sock_sid = SECINITSID_KERNEL;
+			goto authorize;
+		}
+		/*
+		 * hooks.c accepts packets with no socket unconditionally
+		 */
+		nethooks_debug("%s: no sock on this skbuff: non-ICMP\n",
+			       __FUNCTION__);
+		goto out;
+	}
+
+	read_lock_bh(&sk->sk_callback_lock);
+	isec = get_sock_isec(sk);
+
+	/* No isec: allow if any sock can read target */
+	if (!isec) {
+		nethooks_debug("%s: no isec from sock\n", __FUNCTION__);
+		sock_sid = SECINITSID_ANY_SOCKET;
+	}
+	else {
+		sock_sid = isec->sid;
+	}
+	read_unlock_bh(&sk->sk_callback_lock);
+
+
+authorize:
+	/* Selector sid is either set to label or ANY_ASSOC */
+	if (sel->security) {
+		sel_sid = sel->security->ctx_sid;
+		nethooks_debug("%s: %s for context %.50s; sid: %d; sock: %d\n",
+			       __FUNCTION__,
+			       ((dir == FLOW_DIR_IN) ? "input" :
+				((dir == FLOW_DIR_OUT) ? "output" : "forward")),
+			       sel->security->ctx_str,
+			       sel_sid,
+			       sock_sid);
+	}
+
+	rc = avc_has_perm(sock_sid, sel_sid, SECCLASS_ASSOCIATION,
+			  ((dir == FLOW_DIR_IN) ? ASSOCIATION__RECVFROM :
+			   ((dir == FLOW_DIR_OUT) ?  ASSOCIATION__SENDTO :
+			    (ASSOCIATION__SENDTO | ASSOCIATION__RECVFROM))),
+			  NULL);
+
+out:
+	return rc;
+}
+
+/*
+ * Security blob allocation for xfrm_policy and xfrm_state
+ *  -- both attached to selectors
+ */
+static inline int selinux_xfrm_selector_alloc(struct xfrm_selector *sel, struct sadb_x_sec_ctx *sec_ctx)
+{
+	int rc = 0;
+
+	if (!sec_ctx)
+		return -EINVAL;
+
+	nethooks_debug(KERN_NOTICE "%s: got a sec_ctx for policy\n",
+		       __FUNCTION__);
+
+	if (sec_ctx->sadb_x_ctx_len >= PAGE_SIZE)
+		return -ENOMEM;
+
+	sel->security = kmalloc(sizeof(*sel->security) +
+				sec_ctx->sadb_x_ctx_len + 1,
+				GFP_KERNEL);
+
+	if (!sel->security)
+		return -ENOMEM;
+
+	sel->security->ctx_doi = sec_ctx->sadb_x_ctx_doi;
+	sel->security->ctx_len = sec_ctx->sadb_x_ctx_len;
+	sel->security->ctx_alg = sec_ctx->sadb_x_ctx_alg;
+
+	nethooks_debug(KERN_NOTICE "%s: doi %u len %u alg %u\n",
+		       __FUNCTION__,
+		       sel->security->ctx_doi,
+		       sel->security->ctx_len,
+		       sel->security->ctx_alg);
+
+	memcpy(sel->security->ctx_str,
+	       sec_ctx+1,
+	       sel->security->ctx_len);
+	rc = security_context_to_sid(sel->security->ctx_str,
+				     sel->security->ctx_len,
+				     &sel->security->ctx_sid);
+	sel->security->ctx_str[sel->security->ctx_len] = 0;
+
+	nethooks_debug(KERN_NOTICE "%s: context was %s with sid %d\n",
+		       __FUNCTION__,
+		       sel->security->ctx_str,
+		       sel->security->ctx_sid);
+
+	if (rc)
+		kfree(sel->security);
+
+	return rc;
+}
+
+/*
+ * LSM hook implementation that allocs and transfers sec_ctx spec to
+ * xfrm_policy.
+ */
+int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+	int rc = 0;
+
+	if (!xp)
+		return -EINVAL;
+
+	nethooks_debug(KERN_NOTICE "%s: start alloc\n", __FUNCTION__);
+
+	rc = selinux_xfrm_selector_alloc(&xp->selector, sec_ctx);
+
+	return rc;
+}
+
+
+/*
+ * LSM hook implementation that copies security data structure from old to
+ * new for policy cloning.
+ */
+int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+	struct xfrm_sec_ctx *old_ctx, *new_ctx;
+
+	old_ctx = xfrm_policy_security(old);
+
+	if (old_ctx) {
+		new_ctx = new->selector.security =
+			kmalloc(sizeof(*new_ctx) +
+				old_ctx->ctx_len + 1,
+				GFP_KERNEL);
+
+		if (!new_ctx)
+			return -ENOMEM;
+
+		memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
+		memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
+	}
+	return 0;
+}
+
+/*
+ * LSM hook implementation that frees xfrm_policy security information.
+ */
+void selinux_xfrm_policy_free(struct xfrm_policy *xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx)
+		kfree(xfrm_ctx);
+}
+
+/*
+ * LSM hook implementation that allocs and transfers sec_ctx spec to
+ * xfrm_state.
+ */
+int selinux_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+	int rc = 0;
+
+	if (!x)
+		return -EINVAL;
+
+	nethooks_debug(KERN_NOTICE "%s: start alloc\n", __FUNCTION__);
+
+	rc = selinux_xfrm_selector_alloc(&x->sel, sec_ctx);
+
+	return rc;
+}
+
+/*
+ * LSM hook implementation that frees xfrm_state security information.
+ */
+void selinux_xfrm_state_free(struct xfrm_state *x)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_state_security(x);
+
+	if (xfrm_ctx)
+		kfree(xfrm_ctx);
+}
+
+/*
+ * LSM hook that controls access to unlabelled packets.  If
+ * a xfrm_state is authorizable (defined by macro) then it was
+ * already authorized by selector matching process.  If not, then
+ * we need to check for unlabelled access since this may not have
+ * gone thru the selector process.
+ */
+int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
+{
+	int i, rc = 0;
+	struct sec_path *sp;
+	struct sock *sk;
+
+	nethooks_debug("%s: starting\n", __FUNCTION__);
+
+	/* regular check for socket with isec */
+	sp = skb->sp;
+	sk = skb->sk;
+
+	if (sp) {
+		nethooks_debug("%s: sp (0x%x) on skb with length %d\n",
+			       __FUNCTION__,
+			       (unsigned) sp, sp->len);
+
+		/*
+		 * __xfrm_policy_check does not approve unless xfrm_policy_ok
+		 * says that spi's match for policy and the socket.
+		 *
+		 *  Only need to verify the existence of an authorizable sp.
+		 */
+		for (i = 0; i < sp->len; i++) {
+			struct xfrm_state *x = sp->x[i].xvec;
+
+			nethooks_debug("%s: sa: 0x%x\n",
+				       __FUNCTION__,
+				       (unsigned) x);
+
+			if (selinux_authorizable_xfrm(x)) {
+				nethooks_debug("%s: sa 0x%x found\n",
+					       __FUNCTION__,
+					       (unsigned) x);
+				goto accept;
+			}
+		}
+	}
+
+	/* check SELinux sock for unlabelled access */
+	nethooks_debug("%s: before unlabelled sa auth: isec_sid = 0x%x\n",
+		       __FUNCTION__,
+		       (unsigned) isec_sid);
+	rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
+			  ASSOCIATION__RECVFROM, NULL);
+	nethooks_debug("%s: after unlabelled sa auth rc: %d\n",
+		       __FUNCTION__,
+		       rc);
+
+	if (rc)
+		goto drop;
+
+accept:
+	nethooks_debug("%s: accept\n", __FUNCTION__);
+	return 0;
+
+drop:
+	nethooks_debug("%s: drop\n", __FUNCTION__);
+	return rc;
+}
+
+/*
+ * POSTROUTE_LAST hook's XFRM processing:
+ * If we have no security association, then we need to determine
+ * whether the socket is allowed to send to an unlabelled destination.
+ * If we do have a authorizable security association, then it has already been
+ * checked in xfrm_policy_lookup hook.
+ */
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
+{
+	struct dst_entry *dst;
+	int rc = 0;
+
+	dst = skb->dst;
+
+	if (dst) {
+		struct dst_entry *dst_test;
+
+		for (dst_test = dst; dst_test != 0;
+		     dst_test = dst_test->child) {
+			struct xfrm_state *x = dst_test->xfrm;
+
+			if (selinux_authorizable_xfrm(x)) {
+				nethooks_debug("%s: sa 0x%x found\n",
+					       __FUNCTION__,
+					       (unsigned) x);
+				goto accept;
+			}
+		}
+	}
+
+	nethooks_debug("%s: before unlabelled sa auth: isec_sid = 0x%x\n",
+		       __FUNCTION__,
+		       (unsigned) isec_sid);
+	rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
+			  ASSOCIATION__SENDTO, NULL);
+	nethooks_debug("%s: after unlabelled sa auth rc: %d\n", __FUNCTION__, rc);
+
+	if (rc)
+		goto drop;
+
+accept:
+	nethooks_debug("%s: accept\n", __FUNCTION__);
+	return NF_ACCEPT;
+
+drop:
+	nethooks_debug("%s: drop\n", __FUNCTION__);
+	return NF_DROP;
+}
+
+#else  /* CONFIG_SECURITY_NETWORK_XFRM */
+
+int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
+{
+	return 0;
+}
+
+int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
+{
+	return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
_

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Andi Kleen @ 2005-05-17 20:27 UTC (permalink / raw)
  To: David S. Miller; +Cc: dlstevens, akepner, jheffner, netdev, netdev-bounce
In-Reply-To: <20050517.132202.59028935.davem@davemloft.net>

On Tue, May 17, 2005 at 01:22:02PM -0700, David S. Miller wrote:
> From: Andi Kleen <ak@muc.de>
> Date: Tue, 17 May 2005 22:17:36 +0200
> 
> > At least for a directly connected flat network you could get it from ARP.
> 
> So we can make this host based, and store that "arp RTT" thing in the
> inetpeer cache.  :-)

Arghl, you said the "i" word....
Anyways, I think the neighbour cache is fully appropiate, is it not?

But it's not clear such a hack would be worth it anyways. 
If anything it would be probably better to let mountd set the RTTs, e.g. 
implicitely with MSG_CONFIRM (I hope it is using it these days ...) 

-Andi

^ permalink raw reply

* [PATCH 1/2] Resend: LSM-IPSec Networking Hooks
From: jaegert @ 2005-05-17 20:25 UTC (permalink / raw)
  To: netdev, chrisw; +Cc: jaegert, serue, latten, sds, jmorris

Hi,

I am resending these patches because of format errors in the original 
mails.  I apologize for that inconvenience. 

Regards,
Trent.
-----------------------------------
Trent Jaeger
IBM T.J. Watson Research Center
19 Skyline Drive, Hawthorne, NY 10532
(914) 784-7225, (FAX) (914) 784-6209


This patch series implements per packet access control via the
extension of the Linux Security Modules (LSM) interface by hooks in
the XFRM and pfkey subsystems that leverage IPSec security
associations to label packets.  Extensions to the SELinux LSM are
included that leverage the patch for this purpose.

This patch implements the changes necessary to the XFRM subsystem,
pfkey interface, ipv4/ipv6, and xfrm_user interface to restrict a
socket to use only authorized security associations (or no security
association) to send/receive network packets.

Patch purpose:

The patch is designed to enable access control per packets based on
the strongly authenticated IPSec security association.  Such access
controls augment the existing ones based on network interface and IP
address.  The former are very coarse-grained, and the latter can be
spoofed.  By using IPSec, the system can control access to remote
hosts based on cryptographic keys generated using the IPSec mechanism.
This enables access control on a per-machine basis or per-application
if the remote machine is running the same mechanism and trusted to
enforce the access control policy.

Patch design approach:

The overall approach is that policy (xfrm_policy) entries set by
user-level programs (e.g., setkey for ipsec-tools) are extended with a
security context that is used at policy selection time in the XFRM
subsystem to restrict the sockets that can send/receive packets via
security associations (xfrm_states) that are built from those
policies.  

A presentation available at
www.selinux-symposium.org/2005/presentations/session2/2-3-jaeger.pdf
from the SELinux symposium describes the overall approach.

Patch implementation details: 

On output, the policy retrieved (via xfrm_policy_lookup or
xfrm_sk_policy_lookup) must be authorized for the security context of
the socket and the same security context is required for resultant
security association (retrieved or negotiated via racoon in
ipsec-tools).  This is enforced in xfrm_state_find.

On input, the policy retrieved must also be authorized for the socket
(at __xfrm_policy_check), and the security context of the policy must
also match the security association being used.

The patch has virtually no impact on packets that do not use IPSec.
The existing Netfilter (outgoing) and LSM rcv_skb hooks are used as
before.

Also, if IPSec is used without security contexts, the impact is
minimal.  The LSM must allow such policies to be selected for the
combination of socket and remote machine, but subsequent IPSec
processing proceeds as in the original case.

Testing:

The pfkey interface is tested using the ipsec-tools.  ipsec-tools have
been modified (a separate ipsec-tools patch is available for version
0.5) that supports assignment of xfrm_policy entries and security
associations with security contexts via setkey and the negotiation
using the security contexts via racoon.

The xfrm_user interface is tested via ad hoc programs that set
security contexts.  These programs are also available from me, and
contain programs for setting, getting, and deleting policy for testing
this interface.  Testing of sa functions was done by tracing kernel
behavior.

---

 include/linux/pfkeyv2.h  |   13 +++
 include/linux/security.h |  119 +++++++++++++++++++++++++++++++++++
 include/linux/xfrm.h     |   36 ++++++++++
 include/net/flow.h       |    5 -
 include/net/xfrm.h       |   21 ++++++
 net/core/flow.c          |    4 -
 net/ipv4/xfrm4_policy.c  |    2 
 net/ipv6/xfrm6_policy.c  |    2 
 net/key/af_key.c         |  119 +++++++++++++++++++++++++++++++++--
 net/xfrm/xfrm_policy.c   |   64 +++++++++++-------
 net/xfrm/xfrm_state.c    |   14 +++-
 net/xfrm/xfrm_user.c     |  159 +++++++++++++++++++++++++++++++++++++++++++++--
 security/Kconfig         |   13 +++
 security/dummy.c         |   37 ++++++++++
 14 files changed, 568 insertions(+), 40 deletions(-)

diff -puN include/linux/pfkeyv2.h~lsm-xfrm-nethooks include/linux/pfkeyv2.h
--- linux-2.6.12-rc4-nethooks/include/linux/pfkeyv2.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/linux/pfkeyv2.h	2005-05-10 16:19:20.000000000 -0400
@@ -216,6 +216,16 @@ struct sadb_x_nat_t_port {
 } __attribute__((packed));
 /* sizeof(struct sadb_x_nat_t_port) == 8 */
 
+/* Generic LSM security context */
+struct sadb_x_sec_ctx {
+	uint16_t	sadb_x_sec_len;
+	uint16_t	sadb_x_sec_exttype;
+	uint8_t		sadb_x_ctx_alg;  /* LSMs: e.g., selinux == 1 */
+	uint8_t		sadb_x_ctx_doi;
+	uint16_t	sadb_x_ctx_len;
+} __attribute__((packed));
+/* sizeof(struct sadb_sec_ctx) = 8 */
+
 /* Message types */
 #define SADB_RESERVED		0
 #define SADB_GETSPI		1
@@ -324,7 +334,8 @@ struct sadb_x_nat_t_port {
 #define SADB_X_EXT_NAT_T_SPORT		21
 #define SADB_X_EXT_NAT_T_DPORT		22
 #define SADB_X_EXT_NAT_T_OA		23
-#define SADB_EXT_MAX			23
+#define SADB_X_EXT_SEC_CTX		24
+#define SADB_EXT_MAX			24
 
 /* Identity Extension values */
 #define SADB_IDENTTYPE_RESERVED	0
diff -puN include/linux/security.h~lsm-xfrm-nethooks include/linux/security.h
--- linux-2.6.12-rc4-nethooks/include/linux/security.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/linux/security.h	2005-05-16 16:12:29.000000000 -0400
@@ -58,6 +58,12 @@ struct sk_buff;
 struct sock;
 struct sockaddr;
 struct socket;
+struct flowi;
+struct dst_entry;
+struct xfrm_selector;
+struct xfrm_policy;
+struct xfrm_state;
+struct sadb_x_sec_ctx;
 
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb);
@@ -802,6 +808,50 @@ struct swap_info_struct;
  * @sk_free_security:
  *	Deallocate security structure.
  *
+ * Security hooks for XFRM operations.
+ *
+ * @xfrm_policy_alloc_security:
+ *	@xp contains the xfrm_policy being added to Security Policy Database
+ *      used by the XFRM system.
+ *      @sec_ctx contains the security context information being provided by
+ *      the user-level policy update program (e.g., setkey).
+ *      Allocate a security structure to the xp->selector.security field.
+ *      The security field is initialized to NULL when the xfrm_policy is
+ *      allocated.
+ *	Return 0 if operation was successful (memory to allocate, legal context)
+ * @xfrm_policy_clone_security:
+ *      @old contains an existing xfrm_policy in the SPD.
+ *      @new contains a new xfrm_policy being cloned from old.
+ *      Allocate a security structure to the new->selector.security field
+ *      that contains the information from the old->selector.security field.
+ *	Return 0 if operation was successful (memory to allocate).
+ * @xfrm_policy_free_security:
+ *      @xp contains the xfrm_policy
+ *      Deallocate xp->selector.security.
+ * @xfrm_state_alloc_security:
+ *      @x contains the xfrm_state being added to the Security Association
+ *      Database by the XFRM system.
+ *      @sec_ctx contains the security context information being provided by
+ *      the user-level SA generation program (e.g., setkey or racoon).
+ *      Allocate a security structure to the x->sel.security field.  The
+ *      security field is initialized to NULL when the xfrm_state is
+ *      allocated.
+ *	Return 0 if operation was successful (memory to allocate, legal context).
+ * @xfrm_state_free_security:
+ *      @x contains the xfrm_state.
+ *      Deallocate x>sel.security.
+ * @xfrm_policy_lookup:
+ *      @sk contains the sock that is requesting to either send or receive a
+ *      network communication.
+ *      @sel contains the selector that matches the communication end points of
+ *      the network communication (source, destination, and ports).
+ *      @fl contains the flowi that indicates the communication protocol.
+ *      @dir contains the direction of the flow (input or output).
+ *	Check permission when a sock selects a xfrm_policy for processing
+ *      XFRMs on a packet.  The hook is called when selecting either a
+ *      per-socket policy or a generic xfrm policy.
+ *	Return 0 if permission is granted.
+ *
  * Security hooks affecting all System V IPC operations.
  *
  * @ipc_permission:
@@ -1243,6 +1293,15 @@ struct security_operations {
 	int (*sk_alloc_security) (struct sock *sk, int family, int priority);
 	void (*sk_free_security) (struct sock *sk);
 #endif	/* CONFIG_SECURITY_NETWORK */
+
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+	int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx);
+	int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
+	void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+	int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx);
+	void (*xfrm_state_free_security) (struct xfrm_state *x);
+	int (*xfrm_policy_lookup)(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir);
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 };
 
 /* global variables */
@@ -2854,5 +2913,65 @@ static inline void security_sk_free(stru
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+        return security_ops->xfrm_policy_clone_security(old, new);
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+        security_ops->xfrm_policy_free_security(xp);
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return security_ops->xfrm_state_alloc_security(x, sec_ctx);
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+        security_ops->xfrm_state_free_security(x);
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return security_ops->xfrm_policy_lookup(sk, sel, fl, dir);
+}
+#else	/* CONFIG_SECURITY_NETWORK_XFRM */
+static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+{
+}
+
+static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline void security_xfrm_state_free(struct xfrm_state *x)
+{
+}
+
+static inline int security_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
+
 #endif /* ! __LINUX_SECURITY_H */
 
diff -puN include/linux/xfrm.h~lsm-xfrm-nethooks include/linux/xfrm.h
--- linux-2.6.12-rc4-nethooks/include/linux/xfrm.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/linux/xfrm.h	2005-05-10 16:22:40.000000000 -0400
@@ -27,6 +27,22 @@ struct xfrm_id
 	__u8		proto;
 };
 
+struct xfrm_sec_ctx {
+	__u8	ctx_doi;
+	__u8	ctx_alg;
+	__u16	ctx_len;
+	__u32	ctx_sid;
+	char	ctx_str[0];
+};
+
+/* Security Context Domains of Interpretation */
+#define XFRM_SC_DOI_RESERVED 0
+#define XFRM_SC_DOI_LSM 1
+
+/* Security Context Algorithms */
+#define XFRM_SC_ALG_RESERVED 0
+#define XFRM_SC_ALG_SELINUX 1
+
 /* Selector, used as selector both on policy rules (SPD) and SAs. */
 
 struct xfrm_selector
@@ -43,8 +59,15 @@ struct xfrm_selector
 	__u8	proto;
 	int	ifindex;
 	uid_t	user;
+	struct xfrm_sec_ctx *security;
 };
 
+/* All but the security field */
+static inline int xfrm_selector_base_size(void)
+{
+	return sizeof(struct xfrm_selector) - sizeof(struct xfrm_sec_ctx *);
+}
+
 #define XFRM_INF (~(__u64)0)
 
 struct xfrm_lifetime_cfg
@@ -146,6 +169,18 @@ enum {
 
 #define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
 
+/*
+ * Generic LSM security context for comunicating to user space
+ * NOTE: Same format as sadb_x_sec_ctx
+ */
+struct xfrm_user_sec_ctx {
+	__u16			len;
+	__u16			exttype;
+	__u8			ctx_alg;  /* LSMs: e.g., selinux == 1 */
+	__u8			ctx_doi;
+	__u16			ctx_len;
+};
+
 struct xfrm_user_tmpl {
 	struct xfrm_id		id;
 	__u16			family;
@@ -173,6 +208,7 @@ enum xfrm_attr_type_t {
 	XFRMA_ALG_CRYPT,	/* struct xfrm_algo */
 	XFRMA_ALG_COMP,		/* struct xfrm_algo */
 	XFRMA_ENCAP,		/* struct xfrm_algo + struct xfrm_encap_tmpl */
+	XFRMA_SEC_CTX,          /* struct xfrm_sec_ctx */
 	XFRMA_TMPL,		/* 1 or more struct xfrm_user_tmpl */
 	__XFRMA_MAX
 
diff -puN include/net/flow.h~lsm-xfrm-nethooks include/net/flow.h
--- linux-2.6.12-rc4-nethooks/include/net/flow.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/net/flow.h	2005-05-10 15:04:25.000000000 -0400
@@ -84,10 +84,11 @@ struct flowi {
 #define FLOW_DIR_OUT	1
 #define FLOW_DIR_FWD	2
 
-typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir,
+struct sock;
+typedef void (*flow_resolve_t)(struct flowi *key, struct sock *sk, u16 family, u8 dir,
 			       void **objp, atomic_t **obj_refp);
 
-extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+extern void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16 family, u8 dir,
 			       flow_resolve_t resolver);
 extern void flow_cache_flush(void);
 extern atomic_t flow_cache_genid;
diff -puN include/net/xfrm.h~lsm-xfrm-nethooks include/net/xfrm.h
--- linux-2.6.12-rc4-nethooks/include/net/xfrm.h~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/include/net/xfrm.h	2005-05-12 15:38:22.000000000 -0400
@@ -493,6 +493,27 @@ xfrm_selector_match(struct xfrm_selector
 	return 0;
 }
 
+/* If neither has a context --> match
+   Otherwise, both must have a context and the sids, doi, alg must match */
+static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2)
+{
+	return ((!s1 && !s2) ||
+		(s1 && s2 &&
+		 (s1->ctx_sid == s2->ctx_sid) &&
+		 (s1->ctx_doi == s2->ctx_doi) &&
+		 (s1->ctx_alg == s2->ctx_alg)));
+}
+
+static inline struct xfrm_sec_ctx *xfrm_policy_security(struct xfrm_policy *xp)
+{
+	return (xp ? xp->selector.security : NULL);
+}
+
+static inline struct xfrm_sec_ctx *xfrm_state_security(struct xfrm_state *x)
+{
+	return (x ? x->sel.security : NULL);
+}
+
 /* A struct encoding bundle of transformations to apply to some set of flow.
  *
  * dst->child points to the next element of bundle.
diff -puN net/core/flow.c~lsm-xfrm-nethooks net/core/flow.c
--- linux-2.6.12-rc4-nethooks/net/core/flow.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/core/flow.c	2005-05-10 15:04:25.000000000 -0400
@@ -162,7 +162,7 @@ static int flow_key_compare(struct flowi
 	return 0;
 }
 
-void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir,
+void *flow_cache_lookup(struct flowi *key, struct sock *sk, u16 family, u8 dir,
 			flow_resolve_t resolver)
 {
 	struct flow_cache_entry *fle, **head;
@@ -221,7 +221,7 @@ nocache:
 		void *obj;
 		atomic_t *obj_ref;
 
-		resolver(key, family, dir, &obj, &obj_ref);
+		resolver(key, sk, family, dir, &obj, &obj_ref);
 
 		if (fle) {
 			fle->genid = atomic_read(&flow_cache_genid);
diff -puN net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks net/ipv4/xfrm4_policy.c
--- linux-2.6.12-rc4-nethooks/net/ipv4/xfrm4_policy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/ipv4/xfrm4_policy.c	2005-05-16 13:33:47.000000000 -0400
@@ -36,6 +36,8 @@ __xfrm4_find_bundle(struct flowi *fl, st
 		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
 	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
+ 		    xfrm_sec_ctx_match(xfrm_policy_security(policy),
+				       xfrm_state_security(dst->xfrm)) &&
 		    xfrm_bundle_ok(xdst, fl, AF_INET)) {
 			dst_clone(dst);
 			break;
diff -puN net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks net/ipv6/xfrm6_policy.c
--- linux-2.6.12-rc4-nethooks/net/ipv6/xfrm6_policy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/ipv6/xfrm6_policy.c	2005-05-10 15:13:49.000000000 -0400
@@ -54,6 +54,8 @@ __xfrm6_find_bundle(struct flowi *fl, st
 				 xdst->u.rt6.rt6i_src.plen);
 		if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
 		    ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
+ 		    xfrm_sec_ctx_match(xfrm_policy_security(policy),
+ 				       xfrm_state_security(dst->xfrm)) &&
 		    xfrm_bundle_ok(xdst, fl, AF_INET6)) {
 			dst_clone(dst);
 			break;
diff -puN net/key/af_key.c~lsm-xfrm-nethooks net/key/af_key.c
--- linux-2.6.12-rc4-nethooks/net/key/af_key.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/key/af_key.c	2005-05-16 16:13:56.000000000 -0400
@@ -336,6 +336,7 @@ static u8 sadb_ext_min_len[] = {
 	[SADB_X_EXT_NAT_T_SPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
 	[SADB_X_EXT_NAT_T_DPORT]	= (u8) sizeof(struct sadb_x_nat_t_port),
 	[SADB_X_EXT_NAT_T_OA]		= (u8) sizeof(struct sadb_address),
+        [SADB_X_EXT_SEC_CTX]            = (u8) sizeof(struct sadb_x_sec_ctx),
 };
 
 /* Verify sadb_address_{len,prefixlen} against sa_family.  */
@@ -383,6 +384,22 @@ static int verify_address_len(void *p)
 	return 0;
 }
 
+static inline int verify_sec_ctx_len(void *p)
+{
+	struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
+	int len = 0;
+
+	len += sizeof(struct sadb_x_sec_ctx);
+	len += sec_ctx->sadb_x_ctx_len;
+	len += sizeof(uint64_t) - 1;
+	len /= sizeof(uint64_t);
+
+	if (sec_ctx->sadb_x_sec_len != len)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int present_and_same_family(struct sadb_address *src,
 				   struct sadb_address *dst)
 {
@@ -438,6 +455,10 @@ static int parse_exthdrs(struct sk_buff 
 				if (verify_address_len(p))
 					return -EINVAL;
 			}				
+			if (ext_type == SADB_X_EXT_SEC_CTX) {
+				if (verify_sec_ctx_len(p))
+					return -EINVAL;
+			}
 			ext_hdrs[ext_type-1] = p;
 		}
 		p   += ext_len;
@@ -586,6 +607,9 @@ static struct sk_buff * pfkey_xfrm_state
 	struct sadb_key *key;
 	struct sadb_x_sa2 *sa2;
 	struct sockaddr_in *sin;
+	struct sadb_x_sec_ctx *sec_ctx;
+	struct xfrm_sec_ctx *xfrm_ctx;
+	int ctx_size = 0;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	struct sockaddr_in6 *sin6;
 #endif
@@ -609,6 +633,12 @@ static struct sk_buff * pfkey_xfrm_state
 			sizeof(struct sadb_address)*2 + 
 				sockaddr_size*2 +
 					sizeof(struct sadb_x_sa2);
+
+	if ((xfrm_ctx = xfrm_state_security(x))) {
+		ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
+		size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
+        }
+
 	/* identity & sensitivity */
 
 	if ((x->props.family == AF_INET &&
@@ -892,6 +922,20 @@ static struct sk_buff * pfkey_xfrm_state
 		n_port->sadb_x_nat_t_port_reserved = 0;
 	}
 
+	/* security context */
+        if (xfrm_ctx) {
+		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb,
+				sizeof(struct sadb_x_sec_ctx) + ctx_size);
+		sec_ctx->sadb_x_sec_len =
+		  (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t);
+		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+		       xfrm_ctx->ctx_len);
+	}
+
 	return skb;
 }
 
@@ -902,6 +946,7 @@ static struct xfrm_state * pfkey_msg2xfr
 	struct sadb_lifetime *lifetime;
 	struct sadb_sa *sa;
 	struct sadb_key *key;
+	struct sadb_x_sec_ctx *sec_ctx;
 	uint16_t proto;
 	int err;
 	
@@ -984,6 +1029,13 @@ static struct xfrm_state * pfkey_msg2xfr
 		x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime;
 		x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
 	}
+
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	if (sec_ctx != NULL) {
+		if (security_xfrm_state_alloc(x, sec_ctx))
+			goto out;
+	}
+
 	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
 	if (sa->sadb_sa_auth) {
 		int keysize = 0;
@@ -1634,6 +1686,18 @@ parse_ipsecrequests(struct xfrm_policy *
 	return 0;
 }
 
+static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx) {
+		int len = sizeof(struct sadb_x_sec_ctx);
+		len += xfrm_ctx->ctx_len;
+		return PFKEY_ALIGN8(len);
+	}
+	return 0;
+}
+
 static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
 {
 	int sockaddr_size = pfkey_sockaddr_size(xp->family);
@@ -1647,7 +1711,8 @@ static int pfkey_xfrm_policy2msg_size(st
 		(sockaddr_size * 2) +
 		sizeof(struct sadb_x_policy) +
 		(xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) +
-				(socklen * 2)));
+				(socklen * 2))) +
+		pfkey_xfrm_policy2sec_ctx_size(xp);
 }
 
 static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)
@@ -1671,6 +1736,8 @@ static void pfkey_xfrm_policy2msg(struct
 	struct sadb_lifetime *lifetime;
 	struct sadb_x_policy *pol;
 	struct sockaddr_in   *sin;
+	struct sadb_x_sec_ctx *sec_ctx;
+	struct xfrm_sec_ctx *xfrm_ctx;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	struct sockaddr_in6  *sin6;
 #endif
@@ -1855,19 +1922,35 @@ static void pfkey_xfrm_policy2msg(struct
 			}
 		}
 	}
+
+	/* security context */
+        if ((xfrm_ctx = xfrm_policy_security(xp))) {
+		int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp);
+
+		sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, ctx_size);
+		sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t);
+		sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
+		sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi;
+		sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg;
+		sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len;
+		memcpy(sec_ctx + 1, xfrm_ctx->ctx_str,
+		       xfrm_ctx->ctx_len);
+	}
+
 	hdr->sadb_msg_len = size / sizeof(uint64_t);
 	hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
 }
 
 static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
-	int err;
+	int err = 0;
 	struct sadb_lifetime *lifetime;
 	struct sadb_address *sa;
 	struct sadb_x_policy *pol;
 	struct xfrm_policy *xp;
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
+	struct sadb_x_sec_ctx *sec_ctx;
 
 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -1914,6 +1997,12 @@ static int pfkey_spdadd(struct sock *sk,
 	if (xp->selector.dport)
 		xp->selector.dport_mask = ~0;
 
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	if (sec_ctx != NULL) {
+		if (security_xfrm_policy_alloc(xp, sec_ctx))
+			goto out;
+	}
+
 	xp->lft.soft_byte_limit = XFRM_INF;
 	xp->lft.hard_byte_limit = XFRM_INF;
 	xp->lft.soft_packet_limit = XFRM_INF;
@@ -1963,6 +2052,7 @@ static int pfkey_spdadd(struct sock *sk,
 	return 0;
 
 out:
+	security_xfrm_policy_free(xp);
 	kfree(xp);
 	return err;
 }
@@ -1972,10 +2062,11 @@ static int pfkey_spddelete(struct sock *
 	int err;
 	struct sadb_address *sa;
 	struct sadb_x_policy *pol;
-	struct xfrm_policy *xp;
+	struct xfrm_policy *xp, tmp;
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
 	struct xfrm_selector sel;
+	struct sadb_x_sec_ctx *sec_ctx;
 
 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2004,7 +2095,15 @@ static int pfkey_spddelete(struct sock *
 	if (sel.dport)
 		sel.dport_mask = ~0;
 
-	xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1);
+	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	memcpy(&tmp.selector, &sel, sizeof(struct xfrm_selector));
+	if (sec_ctx != NULL) {
+		if (security_xfrm_policy_alloc(&tmp, sec_ctx))
+			goto out;
+	}
+
+	xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &tmp.selector, 1);
+	security_xfrm_policy_free(&tmp);
 	if (xp == NULL)
 		return -ENOENT;
 
@@ -2482,6 +2581,7 @@ static struct xfrm_policy *pfkey_compile
 {
 	struct xfrm_policy *xp;
 	struct sadb_x_policy *pol = (struct sadb_x_policy*)data;
+	struct sadb_x_sec_ctx *sec_ctx;
 
 	switch (family) {
 	case AF_INET:
@@ -2531,10 +2631,21 @@ static struct xfrm_policy *pfkey_compile
 	    (*dir = parse_ipsecrequests(xp, pol)) < 0)
 		goto out;
 
+	/* security context too */
+	if (len >= (pol->sadb_x_policy_len*8 +
+		    sizeof(struct sadb_x_sec_ctx))) {
+		char *p = (char *) pol;
+		p += pol->sadb_x_policy_len*8;
+		sec_ctx = (struct sadb_x_sec_ctx *) p;
+		if (security_xfrm_policy_alloc(xp, sec_ctx))
+			goto out;
+	}
+
 	*dir = pol->sadb_x_policy_dir-1;
 	return xp;
 
 out:
+	security_xfrm_policy_free(xp);
 	kfree(xp);
 	return NULL;
 }
diff -puN net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks net/xfrm/xfrm_policy.c
--- linux-2.6.12-rc4-nethooks/net/xfrm/xfrm_policy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/xfrm/xfrm_policy.c	2005-05-16 16:16:54.000000000 -0400
@@ -257,6 +257,7 @@ void __xfrm_policy_destroy(struct xfrm_p
 	if (del_timer(&policy->timer))
 		BUG();
 
+	security_xfrm_policy_free(policy);
 	kfree(policy);
 }
 EXPORT_SYMBOL(__xfrm_policy_destroy);
@@ -396,7 +397,8 @@ struct xfrm_policy *xfrm_policy_bysel(in
 
 	write_lock_bh(&xfrm_policy_lock);
 	for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) {
-		if (memcmp(sel, &pol->selector, sizeof(*sel)) == 0) {
+		if ((memcmp(sel, &pol->selector, xfrm_selector_base_size()) == 0) &&
+		    (xfrm_sec_ctx_match(sel->security, xfrm_policy_security(pol)))) {
 			xfrm_pol_hold(pol);
 			if (delete)
 				*p = pol->next;
@@ -492,7 +494,7 @@ EXPORT_SYMBOL(xfrm_policy_walk);
 
 /* Find policy to apply to this flow. */
 
-static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir,
+static void xfrm_policy_lookup(struct flowi *fl, struct sock *sk, u16 family, u8 dir,
 			       void **objp, atomic_t **obj_refp)
 {
 	struct xfrm_policy *pol;
@@ -506,9 +508,12 @@ static void xfrm_policy_lookup(struct fl
 			continue;
 
 		match = xfrm_selector_match(sel, fl, family);
+
 		if (match) {
-			xfrm_pol_hold(pol);
-			break;
+ 			if (!security_xfrm_policy_lookup(sk, sel, fl, dir)) {
+				xfrm_pol_hold(pol);
+				break;
+			}
 		}
 	}
 	read_unlock_bh(&xfrm_policy_lock);
@@ -516,15 +521,38 @@ static void xfrm_policy_lookup(struct fl
 		*obj_refp = &pol->refcnt;
 }
 
+static inline int policy_to_flow_dir(int dir)
+{
+	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
+ 	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
+ 	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
+ 		return dir;
+ 	switch (dir) {
+ 	default:
+ 	case XFRM_POLICY_IN:
+ 		return FLOW_DIR_IN;
+ 	case XFRM_POLICY_OUT:
+ 		return FLOW_DIR_OUT;
+ 	case XFRM_POLICY_FWD:
+ 		return FLOW_DIR_FWD;
+	};
+}
+
 static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl)
 {
 	struct xfrm_policy *pol;
 
 	read_lock_bh(&xfrm_policy_lock);
 	if ((pol = sk->sk_policy[dir]) != NULL) {
-		int match = xfrm_selector_match(&pol->selector, fl,
+ 		struct xfrm_selector *sel = &pol->selector;
+ 		int match = xfrm_selector_match(sel, fl,
 						sk->sk_family);
+ 		int err = 0;
+
 		if (match)
+ 			err = security_xfrm_policy_lookup(sk, sel, fl, policy_to_flow_dir(dir));
+
+ 		if (match && !err)
 			xfrm_pol_hold(pol);
 		else
 			pol = NULL;
@@ -595,6 +623,10 @@ static struct xfrm_policy *clone_policy(
 
 	if (newp) {
 		newp->selector = old->selector;
+		if (security_xfrm_policy_clone(old, newp)) {
+			kfree(newp);
+			return (struct xfrm_policy *)NULL;  /* ENOMEM */
+		}
 		newp->lft = old->lft;
 		newp->curlft = old->curlft;
 		newp->action = old->action;
@@ -706,22 +738,6 @@ xfrm_bundle_create(struct xfrm_policy *p
 	return err;
 }
 
-static inline int policy_to_flow_dir(int dir)
-{
-	if (XFRM_POLICY_IN == FLOW_DIR_IN &&
-	    XFRM_POLICY_OUT == FLOW_DIR_OUT &&
-	    XFRM_POLICY_FWD == FLOW_DIR_FWD)
-		return dir;
-	switch (dir) {
-	default:
-	case XFRM_POLICY_IN:
-		return FLOW_DIR_IN;
-	case XFRM_POLICY_OUT:
-		return FLOW_DIR_OUT;
-	case XFRM_POLICY_FWD:
-		return FLOW_DIR_FWD;
-	};
-}
 
 static int stale_bundle(struct dst_entry *dst);
 
@@ -751,7 +767,7 @@ restart:
 		if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT])
 			return 0;
 
-		policy = flow_cache_lookup(fl, family,
+		policy = flow_cache_lookup(fl, sk, family,
 					   policy_to_flow_dir(XFRM_POLICY_OUT),
 					   xfrm_policy_lookup);
 	}
@@ -942,7 +958,7 @@ int __xfrm_policy_check(struct sock *sk,
 		int i;
 
 		for (i=skb->sp->len-1; i>=0; i--) {
-		  struct sec_decap_state *xvec = &(skb->sp->x[i]);
+			struct sec_decap_state *xvec = &(skb->sp->x[i]);
 			if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
 				return 0;
 
@@ -960,7 +976,7 @@ int __xfrm_policy_check(struct sock *sk,
 		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 
 	if (!pol)
-		pol = flow_cache_lookup(&fl, family,
+		pol = flow_cache_lookup(&fl, sk, family,
 					policy_to_flow_dir(dir),
 					xfrm_policy_lookup);
 
diff -puN net/xfrm/xfrm_state.c~lsm-xfrm-nethooks net/xfrm/xfrm_state.c
--- linux-2.6.12-rc4-nethooks/net/xfrm/xfrm_state.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/xfrm/xfrm_state.c	2005-05-16 15:49:41.000000000 -0400
@@ -74,6 +74,7 @@ static void xfrm_state_gc_destroy(struct
 		x->type->destructor(x);
 		xfrm_put_type(x->type);
 	}
+	security_xfrm_state_free(x);
 	kfree(x);
 }
 
@@ -338,7 +339,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
 			      selector.
 			 */
 			if (x->km.state == XFRM_STATE_VALID) {
-				if (!xfrm_selector_match(&x->sel, fl, family))
+				if (!xfrm_selector_match(&x->sel, fl, family) ||
+				    !xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x)))
 					continue;
 				if (!best ||
 				    best->km.dying > x->km.dying ||
@@ -349,7 +351,8 @@ xfrm_state_find(xfrm_address_t *daddr, x
 				acquire_in_progress = 1;
 			} else if (x->km.state == XFRM_STATE_ERROR ||
 				   x->km.state == XFRM_STATE_EXPIRED) {
-				if (xfrm_selector_match(&x->sel, fl, family))
+ 				if (xfrm_selector_match(&x->sel, fl, family) &&
+				    xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x)))
 					error = -ESRCH;
 			}
 		}
@@ -374,6 +377,13 @@ xfrm_state_find(xfrm_address_t *daddr, x
 		xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family);
 
 		if (km_query(x, tmpl, pol) == 0) {
+			if (!xfrm_sec_ctx_match(xfrm_policy_security(pol), xfrm_state_security(x))) {
+				x->km.state = XFRM_STATE_DEAD;
+				xfrm_state_put(x);
+				x = NULL;
+				error = 1;
+				goto out;
+			}
 			x->km.state = XFRM_STATE_ACQ;
 			list_add_tail(&x->bydst, xfrm_state_bydst+h);
 			xfrm_state_hold(x);
diff -puN net/xfrm/xfrm_user.c~lsm-xfrm-nethooks net/xfrm/xfrm_user.c
--- linux-2.6.12-rc4-nethooks/net/xfrm/xfrm_user.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/net/xfrm/xfrm_user.c	2005-05-16 16:20:27.000000000 -0400
@@ -200,6 +200,32 @@ static int attach_encap_tmpl(struct xfrm
 	return 0;
 }
 
+
+static inline int xfrm_user_sec_ctx_size(struct xfrm_policy *xp)
+{
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+	int len;
+
+	if (xfrm_ctx) {
+		len = sizeof(struct xfrm_user_sec_ctx);
+		len += xfrm_ctx->ctx_len;
+		return len;
+	}
+	return 0;
+}
+
+static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg)
+{
+	struct xfrm_user_sec_ctx *uxsc = RTA_DATA(u_arg);
+
+	if (uxsc) {
+		security_xfrm_state_free(x);
+		return security_xfrm_state_alloc(x, uxsc);
+	}
+
+	return 0;
+}
+
 static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
 {
 	memcpy(&x->id, &p->id, sizeof(x->id));
@@ -249,6 +275,9 @@ static struct xfrm_state *xfrm_state_con
 	if (err)
 		goto error;
 
+	if ((err = attach_sec_ctx(x, xfrma[XFRMA_SEC_CTX-1])))
+		goto error;
+
 	x->curlft.add_time = (unsigned long) xtime.tv_sec;
 	x->km.state = XFRM_STATE_VALID;
 	x->km.seq = p->seq;
@@ -335,6 +364,27 @@ struct xfrm_dump_info {
 	int this_idx;
 };
 
+static int dump_one_sec_ctx(struct xfrm_sec_ctx *ctx, struct xfrm_user_sec_ctx *uctx, struct sk_buff *skb, int ctx_size)
+{
+	if (!ctx)
+		return -1;
+
+	uctx->exttype = XFRMA_SEC_CTX;
+	uctx->len = ctx_size;
+	uctx->ctx_doi = ctx->ctx_doi;
+	uctx->ctx_alg = ctx->ctx_alg;
+	uctx->ctx_len = ctx->ctx_len;
+
+	memcpy(uctx + 1, ctx->ctx_str, ctx->ctx_len);
+
+	RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size, uctx);
+
+	return 0;
+
+rtattr_failure:
+	return -1;
+}
+
 static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
 {
 	struct xfrm_dump_info *sp = ptr;
@@ -343,6 +393,7 @@ static int dump_one_state(struct xfrm_st
 	struct xfrm_usersa_info *p;
 	struct nlmsghdr *nlh;
 	unsigned char *b = skb->tail;
+	struct xfrm_sec_ctx *xfrm_ctx;
 
 	if (sp->this_idx < sp->start_idx)
 		goto out;
@@ -367,6 +418,18 @@ static int dump_one_state(struct xfrm_st
 	if (x->encap)
 		RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
 
+	if ((xfrm_ctx = xfrm_state_security(x))) {
+		int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+			xfrm_ctx->ctx_len + 1;
+		struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_KERNEL);
+		int err;
+
+	        err = dump_one_sec_ctx(xfrm_ctx, uctx, skb, ctx_size);
+		kfree(uctx);
+
+		if (err < 0)
+			goto rtattr_failure;
+	}
 	nlh->nlmsg_len = skb->tail - b;
 out:
 	sp->this_idx++;
@@ -580,6 +643,27 @@ static int verify_newpolicy_info(struct 
 	return verify_policy_dir(p->dir);
 }
 
+static int copy_sec_ctx(struct xfrm_policy *pol, struct xfrm_user_sec_ctx *uctx)
+{
+	int err = 0;
+
+	security_xfrm_policy_free(pol);
+	err = security_xfrm_policy_alloc(pol, uctx);
+	return err;
+}
+
+static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct rtattr **xfrma)
+{
+	struct rtattr *rt = xfrma[XFRMA_SEC_CTX-1];
+	struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt);
+
+	if (uctx) {
+		copy_sec_ctx(pol, uctx);
+	}
+
+	return 0;
+}
+
 static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
 			   int nr)
 {
@@ -658,7 +742,10 @@ static struct xfrm_policy *xfrm_policy_c
 	}
 
 	copy_from_user_policy(xp, p);
-	err = copy_from_user_tmpl(xp, xfrma);
+
+	if (!(err = copy_from_user_tmpl(xp, xfrma)))
+		err = copy_from_user_sec_ctx(xp, xfrma);
+
 	if (err) {
 		*errp = err;
 		kfree(xp);
@@ -728,6 +815,27 @@ rtattr_failure:
 	return -1;
 }
 
+static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb, int src)
+{
+	int err = 0;
+	struct xfrm_sec_ctx *xfrm_ctx = xfrm_policy_security(xp);
+
+	if (xfrm_ctx) {
+		int ctx_size = sizeof(struct xfrm_user_sec_ctx) +
+			xfrm_ctx->ctx_len;
+		struct xfrm_user_sec_ctx *uctx = kmalloc(ctx_size, GFP_KERNEL);
+
+		if (!uctx)
+			return -ENOMEM;
+
+	        err = dump_one_sec_ctx(xfrm_ctx, uctx, skb,
+				       ctx_size);
+		kfree(uctx);
+	}
+
+	return err;
+}
+
 static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr)
 {
 	struct xfrm_dump_info *sp = ptr;
@@ -749,6 +857,8 @@ static int dump_one_policy(struct xfrm_p
 	copy_to_user_policy(xp, p, dir);
 	if (copy_to_user_tmpl(xp, skb) < 0)
 		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 0) < 0)
+		goto nlmsg_failure;
 
 	nlh->nlmsg_len = skb->tail - b;
 out:
@@ -804,7 +914,7 @@ static struct sk_buff *xfrm_policy_netli
 
 static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
 {
-	struct xfrm_policy *xp;
+	struct xfrm_policy *xp, tmp;
 	struct xfrm_userpolicy_id *p;
 	int err;
 	int delete;
@@ -818,8 +928,20 @@ static int xfrm_get_policy(struct sk_buf
 
 	if (p->index)
 		xp = xfrm_policy_byid(p->dir, p->index, delete);
-	else
-		xp = xfrm_policy_bysel(p->dir, &p->sel, delete);
+	else {
+		struct rtattr **rtattrs = (struct rtattr **) xfrma;
+		struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1];
+
+		memcpy(&tmp.selector, &p->sel, sizeof(struct xfrm_selector));
+		if (rt) {
+			struct xfrm_user_sec_ctx *uxsc = RTA_DATA(rt);
+
+			if ((err = security_xfrm_policy_alloc(&tmp, uxsc)))
+				return err;
+		}
+		xp = xfrm_policy_bysel(p->dir, &tmp.selector, delete);
+		security_xfrm_policy_free(&tmp);
+	}
 	if (xp == NULL)
 		return -ENOENT;
 
@@ -1101,6 +1223,8 @@ static int build_acquire(struct sk_buff 
 
 	if (copy_to_user_tmpl(xp, skb) < 0)
 		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 1) < 0)
+		goto nlmsg_failure;
 
 	nlh->nlmsg_len = skb->tail - b;
 	return skb->len;
@@ -1114,10 +1238,12 @@ static int xfrm_send_acquire(struct xfrm
 			     struct xfrm_policy *xp, int dir)
 {
 	struct sk_buff *skb;
+	struct xfrm_sec_ctx *ctx;
 	size_t len;
 
 	len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
 	len += NLMSG_SPACE(sizeof(struct xfrm_user_acquire));
+	len += xfrm_user_sec_ctx_size(xp);
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
@@ -1138,8 +1264,9 @@ static struct xfrm_policy *xfrm_compile_
 {
 	struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data;
 	struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1);
+	struct xfrm_user_sec_ctx *uctx;
 	struct xfrm_policy *xp;
-	int nr;
+	int nr = 0;
 
 	switch (family) {
 	case AF_INET:
@@ -1167,9 +1294,26 @@ static struct xfrm_policy *xfrm_compile_
 	    verify_newpolicy_info(p))
 		return NULL;
 
+ 	if (len > (sizeof(*p) + (XFRM_MAX_DEPTH *
+				 sizeof(struct xfrm_user_tmpl)))) {
+ 		struct xfrm_user_tmpl *tmpl;
+ 		uctx = (struct xfrm_user_sec_ctx *) (ut + XFRM_MAX_DEPTH);
+
+ 		if (len != sizeof(*p) +
+		    (XFRM_MAX_DEPTH * sizeof(struct xfrm_user_tmpl)) +
+		    uctx->len)
+ 			return NULL;
+
+                 /* spi must be zero'd unless real tmpl */
+ 		for (tmpl = ut; tmpl->id.spi != 0; tmpl = tmpl + 1)
+ 			nr++;
+ 	}
+ 	else {
+ 		uctx = (struct xfrm_user_sec_ctx *) NULL;
 	nr = ((len - sizeof(*p)) / sizeof(*ut));
 	if (nr > XFRM_MAX_DEPTH)
 		return NULL;
+ 	}
 
 	xp = xfrm_policy_alloc(GFP_KERNEL);
 	if (xp == NULL) {
@@ -1179,6 +1323,8 @@ static struct xfrm_policy *xfrm_compile_
 
 	copy_from_user_policy(xp, p);
 	copy_templates(xp, ut, nr);
+	if (uctx)
+		copy_sec_ctx(xp, uctx);
 
 	*dir = p->dir;
 
@@ -1199,6 +1345,8 @@ static int build_polexpire(struct sk_buf
 	copy_to_user_policy(xp, &upe->pol, dir);
 	if (copy_to_user_tmpl(xp, skb) < 0)
 		goto nlmsg_failure;
+	if (copy_to_user_sec_ctx(xp, skb, 2) < 0)
+		goto nlmsg_failure;
 	upe->hard = !!hard;
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -1216,6 +1364,7 @@ static int xfrm_send_policy_notify(struc
 
 	len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
 	len += NLMSG_SPACE(sizeof(struct xfrm_user_polexpire));
+	len += xfrm_user_sec_ctx_size(xp);
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
diff -puN security/dummy.c~lsm-xfrm-nethooks security/dummy.c
--- linux-2.6.12-rc4-nethooks/security/dummy.c~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/dummy.c	2005-05-10 15:40:22.000000000 -0400
@@ -811,6 +811,35 @@ static inline void dummy_sk_free_securit
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#ifdef CONFIG_SECURITY_NETWORK_XFRM
+static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy *old, struct xfrm_policy *new)
+{
+        return 0;
+}
+
+static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
+{
+}
+
+static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct sadb_x_sec_ctx *sec_ctx)
+{
+        return 0;
+}
+
+static void dummy_xfrm_state_free_security(struct xfrm_state *x)
+{
+}
+
+static int dummy_xfrm_policy_lookup(struct sock *sk, struct xfrm_selector *sel, struct flowi *fl, u8 dir)
+{
+        return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK_XFRM */
 static int dummy_register_security (const char *name, struct security_operations *ops)
 {
 	return -EINVAL;
@@ -992,5 +1021,13 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, sk_alloc_security);
 	set_to_dummy_if_null(ops, sk_free_security);
 #endif	/* CONFIG_SECURITY_NETWORK */
+#ifdef  CONFIG_SECURITY_NETWORK_XFRM
+	set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
+	set_to_dummy_if_null(ops, xfrm_policy_clone_security);
+	set_to_dummy_if_null(ops, xfrm_policy_free_security);
+	set_to_dummy_if_null(ops, xfrm_state_alloc_security);
+	set_to_dummy_if_null(ops, xfrm_state_free_security);
+	set_to_dummy_if_null(ops, xfrm_policy_lookup);
+#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 }
 
diff -puN security/Kconfig~lsm-xfrm-nethooks security/Kconfig
--- linux-2.6.12-rc4-nethooks/security/Kconfig~lsm-xfrm-nethooks	2005-05-10 15:04:25.000000000 -0400
+++ linux-2.6.12-rc4-nethooks-root/security/Kconfig	2005-05-10 15:28:44.000000000 -0400
@@ -53,6 +53,19 @@ config SECURITY_NETWORK
 	  implement socket and networking access controls.
 	  If you are unsure how to answer this question, answer N.
 
+config SECURITY_NETWORK_XFRM
+	bool "XFRM (IPSec) Networking Security Hooks"
+	depends on XFRM && SECURITY_NETWORK
+	help
+	  This enables the XFRM (IPSec) networking security hooks.
+	  If enabled, a security module can use these hooks to
+	  implement per-packet access controls based on labels
+	  derived from IPSec policy.  Non-IPSec communications are
+	  designated as unlabelled, and only sockets authorized
+	  to communicate unlabelled data can send without using
+	  IPSec.
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY_CAPABILITIES
 	tristate "Default Linux Capabilities"
 	depends on SECURITY
_

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: David S. Miller @ 2005-05-17 20:22 UTC (permalink / raw)
  To: ak; +Cc: dlstevens, akepner, jheffner, netdev, netdev-bounce
In-Reply-To: <m1k6lx7gkf.fsf@muc.de>

From: Andi Kleen <ak@muc.de>
Date: Tue, 17 May 2005 22:17:36 +0200

> At least for a directly connected flat network you could get it from ARP.

So we can make this host based, and store that "arp RTT" thing in the
inetpeer cache.  :-)

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Arthur Kepner @ 2005-05-17 20:21 UTC (permalink / raw)
  To: David S.Miller; +Cc: netdev
In-Reply-To: <20050517.114829.115910656.davem@davemloft.net>


On Tue, 17 May 2005, David S.Miller wrote:

> ....
> Can I tell users to call you when they enable the strict
> fragmentation and they can no longer talk UDP to
> remote sites outside of their subnet, or it breaks
> on their heavily SMP machine due to natural system local
> packet reordering?
> ....

I'd much rather take that call than one from a customer 
whose data has been quietly corrupted.

--
Arthur

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Andi Kleen @ 2005-05-17 20:17 UTC (permalink / raw)
  To: David Stevens
  Cc: akepner, David S. Miller, John Heffner, netdev, netdev-bounce
In-Reply-To: <OF0221F508.AD091D99-ON88257004.006D0C52-88257004.006D8293@us.ibm.com>

David Stevens <dlstevens@us.ibm.com> writes:

> Dave,
>         Shouldn't that be an estimator on the destination RTT? Or is that
> what you meant? A fast link locally that traverses a slow path along the 
> way
> would time out too fast.
>         Of course, getting an RTT estimate if there hasn't been TCP 
> traffic
> is a complication. :-)

At least for a directly connected flat network you could get it from ARP.

-Andi

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Rick Jones @ 2005-05-17 20:12 UTC (permalink / raw)
  To: netdev
In-Reply-To: <200505171605.21093.jheffner@psc.edu>


> Timer expiration is not dependent on latency, nor is IP ID wrap time.

IP ID wrap time depends on the rate at which IP datgrams are generated.  That 
will depend on latency if the stuff sitting above IP is latency sensitive and/or 
has not increased its "window" (classic TCP, or number of outstanding NFS 
requests ets) to compensate for latency.

So, it is certainly true that one cannot ass-u-me that a high latency path 
cannot have IP ID wrap, but latency can indeed be a factor in how quickly IP IDs 
will wrap in a given situation.

rick jones

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: John Heffner @ 2005-05-17 20:05 UTC (permalink / raw)
  To: Nivedita Singhvi; +Cc: netdev
In-Reply-To: <428A4B74.4050503@us.ibm.com>

On Tuesday 17 May 2005 03:52 pm, Nivedita Singhvi wrote:
> John Heffner wrote:
> > On Tuesday 17 May 2005 03:25 pm, Nivedita Singhvi wrote:
> >>Yes, a different manifestation of the problem ;). I was talking
> >>in the context of current Linux code and the common ethernet drivers
> >>and typical current Internet/Intranet latencies.
> >
> > The problem is latency independent.
>
> Not entirely - because our reassembly timeout expires, typically.
> (If I understand you right).

Timer expiration is not dependent on latency, nor is IP ID wrap time.

  -John

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: David Stevens @ 2005-05-17 19:56 UTC (permalink / raw)
  To: Andi Kleen; +Cc: akepner, David S. Miller, John Heffner, netdev, netdev-bounce
In-Reply-To: <m1sm0l7jcl.fsf@muc.de>

Dave,
        Shouldn't that be an estimator on the destination RTT? Or is that
what you meant? A fast link locally that traverses a slow path along the 
way
would time out too fast.
        Of course, getting an RTT estimate if there hasn't been TCP 
traffic
is a complication. :-)

                                                +-DLS

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Andi Kleen @ 2005-05-17 19:53 UTC (permalink / raw)
  To: Rick Jones; +Cc: netdev
In-Reply-To: <428A470A.6010703@hp.com>

Rick Jones <rick.jones2@hp.com> writes:

>> Actually, the problem is much worse now - we have virtual
>> partitions in the Xen environment for instance where some
>> packets are headed for local consumption (virtual network,
>> no actual network latency to speak of) and some going
>> out to the network. Having a global IP id generator just
>> won't be able to keep up - we could wrap in submilliseconds...
>
> and the classic TCP sequence number isn't _really_ all that far behind :)

But it has PAWS at least. But I agree even IPv6 fragmentation
with 32bit IDs is not significantly safer.

-Andi

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Nivedita Singhvi @ 2005-05-17 19:52 UTC (permalink / raw)
  To: John Heffner; +Cc: netdev, Rick Jones
In-Reply-To: <200505171531.37167.jheffner@psc.edu>

John Heffner wrote:
> On Tuesday 17 May 2005 03:25 pm, Nivedita Singhvi wrote:
> 
>>Yes, a different manifestation of the problem ;). I was talking
>>in the context of current Linux code and the common ethernet drivers
>>and typical current Internet/Intranet latencies.
> 
> 
> The problem is latency independent.

Not entirely - because our reassembly timeout expires, typically.
(If I understand you right).

thanks,
Nivedita

^ permalink raw reply

* Re: [PATCH 11/12] orinoco: monitor mode support
From: Pavel Roskin @ 2005-05-17 19:43 UTC (permalink / raw)
  To: Francois Romieu; +Cc: Christoph Hellwig, jgarzik, hermes, netdev
In-Reply-To: <20050514173947.GA32235@electric-eye.fr.zoreil.com>

On Sat, 2005-05-14 at 19:39 +0200, Francois Romieu wrote:
> > + drop:
> > +	stats->rx_errors++;
> > +	stats->rx_dropped++;
> > +}
> 
> -> leak (skb).

Indeed.  Thank you!  Please apply this on top of the original patches:

Signed-off-by: Pavel Roskin <proski@gnu.org>

--- orinoco.c
+++ orinoco.c
@@ -1180,7 +1180,7 @@ static void orinoco_rx_monitor(struct ne
 	u16 fc;
 	int err;
 	int len;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
 	hermes_t *hw = &priv->hw;
@@ -1268,6 +1268,8 @@ static void orinoco_rx_monitor(struct ne
  drop:
 	stats->rx_errors++;
 	stats->rx_dropped++;
+	if (skb)
+		dev_kfree_skb_irq(skb);
 }
 
 static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)


-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: Rick Jones @ 2005-05-17 19:33 UTC (permalink / raw)
  To: netdev
In-Reply-To: <428A452B.2010008@us.ibm.com>

> Actually, the problem is much worse now - we have virtual
> partitions in the Xen environment for instance where some
> packets are headed for local consumption (virtual network,
> no actual network latency to speak of) and some going
> out to the network. Having a global IP id generator just
> won't be able to keep up - we could wrap in submilliseconds...

and the classic TCP sequence number isn't _really_ all that far behind :)

>> The larger NFS UDP mount sizes mean more fragments, but intriguingly, 
>> they also mean slower wrap of the IP ID space :)
> 
> 
> True, but in a 32 NIC environment, see how they wrap ;)...

Yep - I'd thought that just about everyone had gone to per-dest or per-route IP 
ID's by now, but even then

rick

^ permalink raw reply

* Re: [RFC/PATCH] "strict" ipv4 reassembly
From: John Heffner @ 2005-05-17 19:31 UTC (permalink / raw)
  To: Nivedita Singhvi, netdev; +Cc: Rick Jones
In-Reply-To: <428A452B.2010008@us.ibm.com>

On Tuesday 17 May 2005 03:25 pm, Nivedita Singhvi wrote:
> Yes, a different manifestation of the problem ;). I was talking
> in the context of current Linux code and the common ethernet drivers
> and typical current Internet/Intranet latencies.

The problem is latency independent.

  -John

^ permalink raw reply


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