|
| 1 | +Message-ID: <20260513041635.1289541-1-vakzz@zellic.io> |
| 2 | +Date: Wed, 13 May 2026 04:16:35 +0000 |
| 3 | +From: William Bowling <vakzz@...lic.io> |
| 4 | +To: netdev@...r.kernel.org |
| 5 | +Cc: "David S . Miller" <davem@...emloft.net>, |
| 6 | + Eric Dumazet <edumazet@...gle.com>, |
| 7 | + Jakub Kicinski <kuba@...nel.org>, |
| 8 | + Paolo Abeni <pabeni@...hat.com>, |
| 9 | + Steffen Klassert <steffen.klassert@...unet.com>, |
| 10 | + Herbert Xu <herbert@...dor.apana.org.au>, |
| 11 | + David Ahern <dsahern@...nel.org>, |
| 12 | + William Bowling <vakzz@...lic.io> |
| 13 | +Subject: [PATCH] net: skbuff: preserve shared-frag marker during coalescing |
| 14 | + |
| 15 | +skb_try_coalesce() can attach paged frags from @from to @to. If @from |
| 16 | +has SKBFL_SHARED_FRAG set, the resulting @to skb can contain the same |
| 17 | +externally-owned or page-cache-backed frags, but the shared-frag marker |
| 18 | +is currently lost. |
| 19 | + |
| 20 | +That breaks the invariant relied on by later in-place writers. In |
| 21 | +particular, ESP input checks skb_has_shared_frag() before deciding |
| 22 | +whether an uncloned nonlinear skb can skip skb_cow_data(). If TCP |
| 23 | +receive coalescing has moved shared frags into an unmarked skb, ESP can |
| 24 | +see skb_has_shared_frag() as false and decrypt in place over page-cache |
| 25 | +backed frags. |
| 26 | + |
| 27 | +Propagate SKBFL_SHARED_FRAG when skb_try_coalesce() transfers paged |
| 28 | +frags. The tailroom copy path does not need the marker because it copies |
| 29 | +bytes into @to's linear data rather than transferring frag descriptors. |
| 30 | + |
| 31 | +Fixes: cef401de7be8 ("net: fix possible wrong checksum generation") |
| 32 | +Fixes: f4c50a4034e6 ("xfrm: esp: avoid in-place decrypt on shared skb frags") |
| 33 | +Signed-off-by: William Bowling <vakzz@...lic.io> |
| 34 | +--- |
| 35 | + net/core/skbuff.c | 2 ++ |
| 36 | + 1 file changed, 2 insertions(+) |
| 37 | + |
| 38 | +diff --git a/net/core/skbuff.c b/net/core/skbuff.c |
| 39 | +index a4695882d1c4..3e8f0b8226ca 100644 |
| 40 | +--- a/net/core/skbuff.c |
| 41 | ++++ b/net/core/skbuff.c |
| 42 | +@@ -6149,6 +6149,8 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, |
| 43 | + from_shinfo->frags, |
| 44 | + from_shinfo->nr_frags * sizeof(skb_frag_t)); |
| 45 | + to_shinfo->nr_frags += from_shinfo->nr_frags; |
| 46 | ++ if (from_shinfo->nr_frags) |
| 47 | ++ to_shinfo->flags |= from_shinfo->flags & SKBFL_SHARED_FRAG; |
| 48 | + |
| 49 | + if (!skb_cloned(from)) |
| 50 | + from_shinfo->nr_frags = 0; |
| 51 | +-- |
| 52 | +2.39.5 |
| 53 | + |
0 commit comments