Patch "net: handle NAPI_GRO_FREE_STOLEN_HEAD case also in napi_frags_finish()" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
net: handle NAPI_GRO_FREE_STOLEN_HEAD case also in napi_frags_finish()
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
net-handle-napi_gro_free_stolen_head-case-also-in-napi_frags_finish.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
e44699d2c28067f69698ccb68dd3ddeacfebc434Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= <[email protected]>
Date: Thu, 29 Jun 2017 11:13:36 +0200
Subject: net: handle NAPI_GRO_FREE_STOLEN_HEAD case also in napi_frags_finish()
From: Michal Kubeček <[email protected]>
commit e44699d2c28067f69698ccb68dd3ddeacfebc434 upstream.
Recently I started seeing warnings about pages with refcount -1. The problem was traced to packets being reused after their head was merged into a GRO packet by skb_gro_receive(). While bisecting the issue pointed to commit c21b48cc1bbf ("net: adjust skb->truesize in ___pskb_trim()") and I have never seen it on a kernel with it reverted, I believe the real problem appeared earlier when the option to merge head frag in GRO was implemented.
Handling NAPI_GRO_FREE_STOLEN_HEAD state was only added to GRO_MERGED_FREE branch of napi_skb_finish() so that if the driver uses napi_gro_frags() and head is merged (which in my case happens after the skb_condense() call added by the commit mentioned above), the skb is reused including the head that has been merged. As a result, we release the page reference twice and eventually end up with negative page refcount.
To fix the problem, handle NAPI_GRO_FREE_STOLEN_HEAD in napi_frags_finish() the same way it's done in napi_skb_finish().
--- net/core/dev.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
net/core/dev.c +16 -6
@@ -4375,6 +4375,12 @@ struct packet_offload *gro_find_complete }EXPORT_SYMBOL (gro_find_complete_by_type); +static void napi_skb_free_stolen_head (struct sk_buff *skb) +{ +skb_dst_drop (skb); +kmem_cache_free (skbuff_head_cache, skb); +} +static gro_result_t napi_skb_finish (gro_result_t ret,struct sk_buff *skb) {switch (ret) {
@@ -4388,12 +4394,10 @@ static gro_result_t napi_skb_finish(gro_break ;case GRO_MERGED_FREE : -if (NAPI_GRO_CB (skb)->free ==NAPI_GRO_FREE_STOLEN_HEAD ) { -skb_dst_drop (skb); -kmem_cache_free (skbuff_head_cache, skb); - }else { +if (NAPI_GRO_CB (skb)->free ==NAPI_GRO_FREE_STOLEN_HEAD ) +napi_skb_free_stolen_head (skb); +else __kfree_skb (skb); - }break ;case GRO_HELD :
@@ -4459,10 +4463,16 @@ static gro_result_t napi_frags_finish(stbreak ;case GRO_DROP : -case GRO_MERGED_FREE :napi_reuse_skb (napi, skb);break ; +case GRO_MERGED_FREE : +if (NAPI_GRO_CB (skb)->free ==NAPI_GRO_FREE_STOLEN_HEAD ) +napi_skb_free_stolen_head (skb); +else +napi_reuse_skb (napi, skb); +break ; +case GRO_MERGED :break ; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/net-handle-napi_gro_free_stolen_head-case-also-in-napi_frags_finish.patch