There are a number of paths where an oversize skb could be sent to a driver. The driver should not be required to check for this - the core layer should do it instead.
Add a check to validate_xmit_skb that checks both GSO and non-GSO packets and drops them if they are too large. Signed-off-by: Daniel Axtens <d...@axtens.net> --- net/core/dev.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 6c96c26aadbf..f09eece2cd21 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1830,13 +1830,11 @@ static inline void net_timestamp_set(struct sk_buff *skb) __net_timestamp(SKB); \ } \ -bool is_skb_forwardable(const struct net_device *dev, const struct sk_buff *skb) +static inline bool skb_mac_len_fits_dev(const struct net_device *dev, + const struct sk_buff *skb) { unsigned int len; - if (!(dev->flags & IFF_UP)) - return false; - len = dev->mtu + dev->hard_header_len + VLAN_HLEN; if (skb->len <= len) return true; @@ -1850,6 +1848,14 @@ bool is_skb_forwardable(const struct net_device *dev, const struct sk_buff *skb) return false; } + +bool is_skb_forwardable(const struct net_device *dev, const struct sk_buff *skb) +{ + if (!(dev->flags & IFF_UP)) + return false; + + return skb_mac_len_fits_dev(dev, skb); +} EXPORT_SYMBOL_GPL(is_skb_forwardable); int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb) @@ -3081,6 +3087,9 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device if (unlikely(!skb)) goto out_null; + if (unlikely(!skb_mac_len_fits_dev(dev, skb))) + goto out_kfree_skb; + if (netif_needs_gso(skb, features)) { struct sk_buff *segs; -- 2.14.1