Messages in this thread Patch in this message | | | From | <> | Subject | [PATCH net] net: drop pulled SKB_GSO_FRAGLIST skb | Date | Sun, 28 Apr 2024 22:30:10 +0800 |
| |
From: Shiming Cheng <shiming.cheng@mediatek.com>
A SKB_GSO_FRAGLIST skb without GSO_BY_FRAGS is expected to have all segments except the last to be gso_size long. If this does not hold, the skb has been modified and the fraglist gso integrity is lost. Drop the packet, as it cannot be segmented correctly by skb_segment_list.
The skb could be salvaged. By linearizing, dropping the SKB_GSO_FRAGLIST bit and entering the normal skb_segment path rather than the skb_segment_list path.
That choice is currently made in the protocol caller, __udp_gso_segment. It's not trivial to add such a backup path here. So let's add this backstop against kernel crashes.
Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.") Signed-off-by: Shiming Cheng <shiming.cheng@mediatek.com> Signed-off-by: Lena Wang <lena.wang@mediatek.com> --- net/core/skbuff.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b99127712e67..4777f5fea6c3 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4491,6 +4491,7 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, { struct sk_buff *list_skb = skb_shinfo(skb)->frag_list; unsigned int tnl_hlen = skb_tnl_header_len(skb); + unsigned int mss = skb_shinfo(skb)->gso_size; unsigned int delta_truesize = 0; unsigned int delta_len = 0; struct sk_buff *tail = NULL; @@ -4504,6 +4505,9 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb, if (err) goto err_linearize; + if (mss != GSO_BY_FRAGS && mss != skb_headlen(skb)) + return ERR_PTR(-EFAULT); + skb_shinfo(skb)->frag_list = NULL; while (list_skb) { -- 2.18.0
| |