On Sun, Aug 17, 2003 at 11:20:19PM -0700, David S. Miller wrote: > > So at least two things need to be changed in Herbert's patch: > > 1) Must add check for necessary SKB header space before > copying data in front of skb->data Do we really need this considering that the MAC header was there to begin with? > 2) SKB must be made unshared for mangling. OK, here is the patch which does that. Cheers, -- Debian GNU/Linux 3.0 is out! ( http://www.debian.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
Index: kernel-source-2.5/net/ipv4/xfrm4_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/xfrm4_input.c,v retrieving revision 1.5 diff -u -r1.5 xfrm4_input.c --- kernel-source-2.5/net/ipv4/xfrm4_input.c 9 Aug 2003 03:42:54 -0000 1.5 +++ kernel-source-2.5/net/ipv4/xfrm4_input.c 19 Aug 2003 12:12:24 -0000 @@ -9,6 +9,7 @@ * */ +#include <linux/string.h> #include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> @@ -49,6 +50,9 @@ struct xfrm_state *x; int xfrm_nr = 0; int decaps = 0; + int hhlen; + + hhlen = skb->nh.raw - skb->mac.raw; if ((err = xfrm4_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0) goto drop; @@ -95,10 +99,14 @@ if (x->props.mode) { if (iph->protocol != IPPROTO_IPIP) goto drop; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto drop; + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto drop; skb->nh.raw = skb->data; if (!(x->props.flags & XFRM_STATE_NOECN)) ipip_ecn_decapsulate(iph, skb); - iph = skb->nh.iph; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); decaps = 1; break; @@ -126,6 +134,9 @@ skb->sp->len += xfrm_nr; if (decaps) { + if (hhlen) + skb->mac.raw = + memmove(skb->data - hhlen, skb->mac.raw, hhlen); if (!(skb->dev->flags&IFF_LOOPBACK)) { dst_release(skb->dst); skb->dst = NULL; Index: kernel-source-2.5/net/ipv6/xfrm6_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/xfrm6_input.c,v retrieving revision 1.4 diff -u -r1.4 xfrm6_input.c --- kernel-source-2.5/net/ipv6/xfrm6_input.c 29 Jul 2003 11:11:34 -0000 1.4 +++ kernel-source-2.5/net/ipv6/xfrm6_input.c 19 Aug 2003 12:12:56 -0000 @@ -9,6 +9,7 @@ * IPv6 support */ +#include <linux/string.h> #include <net/inet_ecn.h> #include <net/ip.h> #include <net/ipv6.h> @@ -33,10 +34,12 @@ int decaps = 0; int nexthdr = 0; u8 *prevhdr = NULL; + int hhlen; ip6_find_1stfragopt(skb, &prevhdr); nexthdr = *prevhdr; *nhoffp = prevhdr - skb->nh.raw; + hhlen = skb->nh.raw - skb->mac.raw; if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) goto drop; @@ -77,10 +80,14 @@ if (x->props.mode) { /* XXX */ if (nexthdr != IPPROTO_IPV6) goto drop; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto drop; + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto drop; skb->nh.raw = skb->data; if (!(x->props.flags & XFRM_STATE_NOECN)) ipip6_ecn_decapsulate(iph, skb); - iph = skb->nh.ipv6h; decaps = 1; break; } @@ -108,6 +115,9 @@ skb->ip_summed = CHECKSUM_NONE; if (decaps) { + if (hhlen) + skb->mac.raw = + memmove(skb->data - hhlen, skb->mac.raw, hhlen); if (!(skb->dev->flags&IFF_LOOPBACK)) { dst_release(skb->dst); skb->dst = NULL;