Messages in this thread Patch in this message | | | Date | Fri, 22 Feb 2008 16:30:45 -0800 | From | Greg KH <> | Subject | [patch 20/38] INET: Prevent out-of-sync truesize on ip_fragment slow path |
| |
2.6.24-stable review patch. If anyone has any objections, please let us know.
------------------ Upstream commit: 29ffe1a5c52dae13b6efead97aab9b058f38fce4
When ip_fragment has to hit the slow path the value of skb->truesize may go out of sync because we would have updated it without changing the packet length. This violates the constraints on truesize.
This patch postpones the update of skb->truesize to prevent this.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
--- net/ipv4/ip_output.c | 4 +++- net/ipv6/ip6_output.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-)
--- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -462,6 +462,7 @@ int ip_fragment(struct sk_buff *skb, int if (skb_shinfo(skb)->frag_list) { struct sk_buff *frag; int first_len = skb_pagelen(skb); + int truesizes = 0; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -485,7 +486,7 @@ int ip_fragment(struct sk_buff *skb, int sock_hold(skb->sk); frag->sk = skb->sk; frag->destructor = sock_wfree; - skb->truesize -= frag->truesize; + truesizes += frag->truesize; } } @@ -496,6 +497,7 @@ int ip_fragment(struct sk_buff *skb, int frag = skb_shinfo(skb)->frag_list; skb_shinfo(skb)->frag_list = NULL; skb->data_len = first_len - skb_headlen(skb); + skb->truesize -= truesizes; skb->len = first_len; iph->tot_len = htons(first_len); iph->frag_off = htons(IP_MF); --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -609,6 +609,7 @@ static int ip6_fragment(struct sk_buff * if (skb_shinfo(skb)->frag_list) { int first_len = skb_pagelen(skb); + int truesizes = 0; if (first_len - hlen > mtu || ((first_len - hlen) & 7) || @@ -631,7 +632,7 @@ static int ip6_fragment(struct sk_buff * sock_hold(skb->sk); frag->sk = skb->sk; frag->destructor = sock_wfree; - skb->truesize -= frag->truesize; + truesizes += frag->truesize; } } @@ -662,6 +663,7 @@ static int ip6_fragment(struct sk_buff * first_len = skb_pagelen(skb); skb->data_len = first_len - skb_headlen(skb); + skb->truesize -= truesizes; skb->len = first_len; ipv6_hdr(skb)->payload_len = htons(first_len - sizeof(struct ipv6hdr)); --
| |