Commit 4497b0763cb1afae463f5e144c28b5d806e28b60

Authored by Ben Hutchings
Committed by David S. Miller
1 parent 0187bdfb05

net: Discard and warn about LRO'd skbs received for forwarding

Add skb_warn_if_lro() to test whether an skb was received with LRO and
warn if so.

Change br_forward(), ip_forward() and ip6_forward() to call it) and
discard the skb if it returns true.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 5 changed files with 29 additions and 1 deletions Side-by-side Diff

include/linux/skbuff.h
... ... @@ -1702,6 +1702,20 @@
1702 1702 return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6;
1703 1703 }
1704 1704  
  1705 +extern void __skb_warn_lro_forwarding(const struct sk_buff *skb);
  1706 +
  1707 +static inline bool skb_warn_if_lro(const struct sk_buff *skb)
  1708 +{
  1709 + /* LRO sets gso_size but not gso_type, whereas if GSO is really
  1710 + * wanted then gso_type will be set. */
  1711 + struct skb_shared_info *shinfo = skb_shinfo(skb);
  1712 + if (shinfo->gso_size != 0 && unlikely(shinfo->gso_type == 0)) {
  1713 + __skb_warn_lro_forwarding(skb);
  1714 + return true;
  1715 + }
  1716 + return false;
  1717 +}
  1718 +
1705 1719 static inline void skb_forward_csum(struct sk_buff *skb)
1706 1720 {
1707 1721 /* Unfortunately we don't support this one. Any brave souls? */
net/bridge/br_forward.c
... ... @@ -89,7 +89,7 @@
89 89 /* called with rcu_read_lock */
90 90 void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
91 91 {
92   - if (should_deliver(to, skb)) {
  92 + if (!skb_warn_if_lro(skb) && should_deliver(to, skb)) {
93 93 __br_forward(to, skb);
94 94 return;
95 95 }
... ... @@ -2583,6 +2583,13 @@
2583 2583 return true;
2584 2584 }
2585 2585  
  2586 +void __skb_warn_lro_forwarding(const struct sk_buff *skb)
  2587 +{
  2588 + if (net_ratelimit())
  2589 + pr_warning("%s: received packets cannot be forwarded"
  2590 + " while LRO is enabled\n", skb->dev->name);
  2591 +}
  2592 +
2586 2593 EXPORT_SYMBOL(___pskb_trim);
2587 2594 EXPORT_SYMBOL(__kfree_skb);
2588 2595 EXPORT_SYMBOL(kfree_skb);
... ... @@ -2616,6 +2623,7 @@
2616 2623 EXPORT_SYMBOL(skb_abort_seq_read);
2617 2624 EXPORT_SYMBOL(skb_find_text);
2618 2625 EXPORT_SYMBOL(skb_append_datato_frags);
  2626 +EXPORT_SYMBOL(__skb_warn_lro_forwarding);
2619 2627  
2620 2628 EXPORT_SYMBOL_GPL(skb_to_sgvec);
2621 2629 EXPORT_SYMBOL_GPL(skb_cow_data);
net/ipv4/ip_forward.c
... ... @@ -56,6 +56,9 @@
56 56 struct rtable *rt; /* Route we use */
57 57 struct ip_options * opt = &(IPCB(skb)->opt);
58 58  
  59 + if (skb_warn_if_lro(skb))
  60 + goto drop;
  61 +
59 62 if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb))
60 63 goto drop;
61 64  
net/ipv6/ip6_output.c
... ... @@ -407,6 +407,9 @@
407 407 if (ipv6_devconf.forwarding == 0)
408 408 goto error;
409 409  
  410 + if (skb_warn_if_lro(skb))
  411 + goto drop;
  412 +
410 413 if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) {
411 414 IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS);
412 415 goto drop;