ipv4: ip_do_fragment: fix headroom tests
Some time ago David Woodhouse reported skb_under_panic
when we try to push ethernet header to fragmented ipv6 skbs.
It was fixed for ipv6 by Florian Westphal in
commit 1d325d217c
("ipv6: ip6_fragment: fix headroom tests and skb leak")
However similar problem still exist in ipv4.
It does not trigger skb_under_panic due paranoid check
in ip_finish_output2, however according to Alexey Kuznetsov
current state is abnormal and ip_fragment should be fixed too.
Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
e36fef66f4
Коммит
254d900b80
|
@ -599,6 +599,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
|
||||||
hlen = iph->ihl * 4;
|
hlen = iph->ihl * 4;
|
||||||
mtu = mtu - hlen; /* Size of data space */
|
mtu = mtu - hlen; /* Size of data space */
|
||||||
IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE;
|
IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE;
|
||||||
|
ll_rs = LL_RESERVED_SPACE(rt->dst.dev);
|
||||||
|
|
||||||
/* When frag_list is given, use it. First, check its validity:
|
/* When frag_list is given, use it. First, check its validity:
|
||||||
* some transformers could create wrong frag_list or break existing
|
* some transformers could create wrong frag_list or break existing
|
||||||
|
@ -614,14 +615,15 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
|
||||||
if (first_len - hlen > mtu ||
|
if (first_len - hlen > mtu ||
|
||||||
((first_len - hlen) & 7) ||
|
((first_len - hlen) & 7) ||
|
||||||
ip_is_fragment(iph) ||
|
ip_is_fragment(iph) ||
|
||||||
skb_cloned(skb))
|
skb_cloned(skb) ||
|
||||||
|
skb_headroom(skb) < ll_rs)
|
||||||
goto slow_path;
|
goto slow_path;
|
||||||
|
|
||||||
skb_walk_frags(skb, frag) {
|
skb_walk_frags(skb, frag) {
|
||||||
/* Correct geometry. */
|
/* Correct geometry. */
|
||||||
if (frag->len > mtu ||
|
if (frag->len > mtu ||
|
||||||
((frag->len & 7) && frag->next) ||
|
((frag->len & 7) && frag->next) ||
|
||||||
skb_headroom(frag) < hlen)
|
skb_headroom(frag) < hlen + ll_rs)
|
||||||
goto slow_path_clean;
|
goto slow_path_clean;
|
||||||
|
|
||||||
/* Partially cloned skb? */
|
/* Partially cloned skb? */
|
||||||
|
@ -711,8 +713,6 @@ slow_path:
|
||||||
left = skb->len - hlen; /* Space per frame */
|
left = skb->len - hlen; /* Space per frame */
|
||||||
ptr = hlen; /* Where to start from */
|
ptr = hlen; /* Where to start from */
|
||||||
|
|
||||||
ll_rs = LL_RESERVED_SPACE(rt->dst.dev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fragment the datagram.
|
* Fragment the datagram.
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче