Commit 734c53f3 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Fix for UDP and TCP NAT on nonlinear skbs

UDP and TCP refer to potentially stale pointers after calling
skb_ip_make_writable(), and UDP calls it with the wrong len argument.
All found by nfsim.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent cec8e411
...@@ -91,8 +91,8 @@ tcp_manip_pkt(struct sk_buff **pskb, ...@@ -91,8 +91,8 @@ tcp_manip_pkt(struct sk_buff **pskb,
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct tcphdr *hdr; struct tcphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4; unsigned int hdroff = iphdroff + iph->ihl*4;
u_int32_t oldip; u32 oldip, oldsrc = iph->saddr, olddst = iph->daddr;
u_int16_t *portptr, oldport; u16 *portptr, oldport;
int hdrsize = 8; /* TCP connection tracking guarantees this much */ int hdrsize = 8; /* TCP connection tracking guarantees this much */
/* this could be a inner header returned in icmp packet; in such /* this could be a inner header returned in icmp packet; in such
...@@ -108,11 +108,11 @@ tcp_manip_pkt(struct sk_buff **pskb, ...@@ -108,11 +108,11 @@ tcp_manip_pkt(struct sk_buff **pskb,
if (maniptype == IP_NAT_MANIP_SRC) { if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */ /* Get rid of src ip and src pt */
oldip = iph->saddr; oldip = oldsrc;
portptr = &hdr->source; portptr = &hdr->source;
} else { } else {
/* Get rid of dst ip and dst pt */ /* Get rid of dst ip and dst pt */
oldip = iph->daddr; oldip = olddst;
portptr = &hdr->dest; portptr = &hdr->dest;
} }
......
...@@ -90,20 +90,20 @@ udp_manip_pkt(struct sk_buff **pskb, ...@@ -90,20 +90,20 @@ udp_manip_pkt(struct sk_buff **pskb,
struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
struct udphdr *hdr; struct udphdr *hdr;
unsigned int hdroff = iphdroff + iph->ihl*4; unsigned int hdroff = iphdroff + iph->ihl*4;
u_int32_t oldip; u32 oldip, oldsrc = iph->saddr, olddst = iph->daddr;
u_int16_t *portptr; u16 *portptr;
if (!skb_ip_make_writable(pskb, hdroff + sizeof(hdr))) if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr)))
return 0; return 0;
hdr = (void *)(*pskb)->data + hdroff; hdr = (void *)(*pskb)->data + hdroff;
if (maniptype == IP_NAT_MANIP_SRC) { if (maniptype == IP_NAT_MANIP_SRC) {
/* Get rid of src ip and src pt */ /* Get rid of src ip and src pt */
oldip = iph->saddr; oldip = oldsrc;
portptr = &hdr->source; portptr = &hdr->source;
} else { } else {
/* Get rid of dst ip and dst pt */ /* Get rid of dst ip and dst pt */
oldip = iph->daddr; oldip = olddst;
portptr = &hdr->dest; portptr = &hdr->dest;
} }
if (hdr->check) /* 0 is a special case meaning no checksum */ if (hdr->check) /* 0 is a special case meaning no checksum */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment