]>
Commit | Line | Data |
---|---|---|
43c68a09 GKH |
1 | From foo@baz Sat Apr 16 09:15:18 PDT 2016 |
2 | From: Jakub Sitnicki <jkbs@redhat.com> | |
3 | Date: Tue, 5 Apr 2016 18:41:08 +0200 | |
4 | Subject: ipv6: Count in extension headers in skb->network_header | |
5 | ||
6 | From: Jakub Sitnicki <jkbs@redhat.com> | |
7 | ||
8 | [ Upstream commit 3ba3458fb9c050718b95275a3310b74415e767e2 ] | |
9 | ||
10 | When sending a UDPv6 message longer than MTU, account for the length | |
11 | of fragmentable IPv6 extension headers in skb->network_header offset. | |
12 | Same as we do in alloc_new_skb path in __ip6_append_data(). | |
13 | ||
14 | This ensures that later on __ip6_make_skb() will make space in | |
15 | headroom for fragmentable extension headers: | |
16 | ||
17 | /* move skb->data to ip header from ext header */ | |
18 | if (skb->data < skb_network_header(skb)) | |
19 | __skb_pull(skb, skb_network_offset(skb)); | |
20 | ||
21 | Prevents a splat due to skb_under_panic: | |
22 | ||
23 | skbuff: skb_under_panic: text:ffffffff8143397b len:2126 put:14 \ | |
24 | head:ffff880005bacf50 data:ffff880005bacf4a tail:0x48 end:0xc0 dev:lo | |
25 | ------------[ cut here ]------------ | |
26 | kernel BUG at net/core/skbuff.c:104! | |
27 | invalid opcode: 0000 [#1] KASAN | |
28 | CPU: 0 PID: 160 Comm: reproducer Not tainted 4.6.0-rc2 #65 | |
29 | [...] | |
30 | Call Trace: | |
31 | [<ffffffff813eb7b9>] skb_push+0x79/0x80 | |
32 | [<ffffffff8143397b>] eth_header+0x2b/0x100 | |
33 | [<ffffffff8141e0d0>] neigh_resolve_output+0x210/0x310 | |
34 | [<ffffffff814eab77>] ip6_finish_output2+0x4a7/0x7c0 | |
35 | [<ffffffff814efe3a>] ip6_output+0x16a/0x280 | |
36 | [<ffffffff815440c1>] ip6_local_out+0xb1/0xf0 | |
37 | [<ffffffff814f1115>] ip6_send_skb+0x45/0xd0 | |
38 | [<ffffffff81518836>] udp_v6_send_skb+0x246/0x5d0 | |
39 | [<ffffffff8151985e>] udpv6_sendmsg+0xa6e/0x1090 | |
40 | [...] | |
41 | ||
42 | Reported-by: Ji Jianwen <jiji@redhat.com> | |
43 | Signed-off-by: Jakub Sitnicki <jkbs@redhat.com> | |
44 | Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> | |
45 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
46 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
47 | --- | |
48 | net/ipv6/ip6_output.c | 8 ++++---- | |
49 | 1 file changed, 4 insertions(+), 4 deletions(-) | |
50 | ||
51 | --- a/net/ipv6/ip6_output.c | |
52 | +++ b/net/ipv6/ip6_output.c | |
53 | @@ -1091,8 +1091,8 @@ static inline int ip6_ufo_append_data(st | |
54 | int getfrag(void *from, char *to, int offset, int len, | |
55 | int odd, struct sk_buff *skb), | |
56 | void *from, int length, int hh_len, int fragheaderlen, | |
57 | - int transhdrlen, int mtu, unsigned int flags, | |
58 | - const struct flowi6 *fl6) | |
59 | + int exthdrlen, int transhdrlen, int mtu, | |
60 | + unsigned int flags, const struct flowi6 *fl6) | |
61 | ||
62 | { | |
63 | struct sk_buff *skb; | |
64 | @@ -1117,7 +1117,7 @@ static inline int ip6_ufo_append_data(st | |
65 | skb_put(skb, fragheaderlen + transhdrlen); | |
66 | ||
67 | /* initialize network header pointer */ | |
68 | - skb_reset_network_header(skb); | |
69 | + skb_set_network_header(skb, exthdrlen); | |
70 | ||
71 | /* initialize protocol header pointer */ | |
72 | skb->transport_header = skb->network_header + fragheaderlen; | |
73 | @@ -1359,7 +1359,7 @@ emsgsize: | |
74 | (rt->dst.dev->features & NETIF_F_UFO) && | |
75 | (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) { | |
76 | err = ip6_ufo_append_data(sk, queue, getfrag, from, length, | |
77 | - hh_len, fragheaderlen, | |
78 | + hh_len, fragheaderlen, exthdrlen, | |
79 | transhdrlen, mtu, flags, fl6); | |
80 | if (err) | |
81 | goto error; |