Skip to content

Commit bf5a58d

Browse files
melvergregkh
authored andcommitted
net: fix up truesize of cloned skb in skb_prepare_for_shift()
commit 097b914 upstream. Avoid the assumption that ksize(kmalloc(S)) == ksize(kmalloc(S)): when cloning an skb, save and restore truesize after pskb_expand_head(). This can occur if the allocator decides to service an allocation of the same size differently (e.g. use a different size class, or pass the allocation on to KFENCE). Because truesize is used for bookkeeping (such as sk_wmem_queued), a modified truesize of a cloned skb may result in corrupt bookkeeping and relevant warnings (such as in sk_stream_kill_queues()). Link: https://lkml.kernel.org/r/X9JR/[email protected] Reported-by: [email protected] Suggested-by: Eric Dumazet <[email protected]> Signed-off-by: Marco Elver <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f5fb0ee commit bf5a58d

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

net/core/skbuff.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3292,7 +3292,19 @@ EXPORT_SYMBOL(skb_split);
32923292
*/
32933293
static int skb_prepare_for_shift(struct sk_buff *skb)
32943294
{
3295-
return skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
3295+
int ret = 0;
3296+
3297+
if (skb_cloned(skb)) {
3298+
/* Save and restore truesize: pskb_expand_head() may reallocate
3299+
* memory where ksize(kmalloc(S)) != ksize(kmalloc(S)), but we
3300+
* cannot change truesize at this point.
3301+
*/
3302+
unsigned int save_truesize = skb->truesize;
3303+
3304+
ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
3305+
skb->truesize = save_truesize;
3306+
}
3307+
return ret;
32963308
}
32973309

32983310
/**

0 commit comments

Comments
 (0)