Re: [PATCH] gianfar: fix potential sk_wmem_alloc imbalance
From: Paul Gortmaker <hidden>
Date: 2012-07-06 18:10:06
[[PATCH] gianfar: fix potential sk_wmem_alloc imbalance] On 05/07/2012 (Thu 23:45) Eric Dumazet wrote:
From: Eric Dumazet <edumazet@google.com> commit db83d136d7f753 (gianfar: Fix missing sock reference when processing TX time stamps) added a potential sk_wmem_alloc imbalance If the new skb has a different truesize than old one, we can get a negative sk_wmem_alloc once new skb is orphaned at TX completion. Now we no longer early orphan skbs in dev_hard_start_xmit(), this probably can lead to fatal bugs. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Manfred Rudigier <redacted> Cc: Claudiu Manoil <redacted> Cc: Jiajun Wu <redacted> Cc: Paul Gortmaker <redacted> Cc: Andy Fleming <redacted> --- Note : I don't have the hardware and discovered this problem by code analysis. So please compile and run this patch before Acking it, thanks !
I can do that on Monday when I'm back in the office if nobody else has already done it by then.
BTW, dev->needed_headroom should be set to GMAC_FCB_LEN + GMAC_TXPAL_LEN to avoid reallocations...
Aside from the one line change at driver init, is there more to it than that? More specifically, it currently does: fcb_length = GMAC_FCB_LEN; if (...timestamps...) fcb_length = GMAC_FCB_LEN + GMAC_TXPAL_LEN; if (... && (skb_headroom(skb) < fcb_length)) ... skb_new = skb_realloc_headroom(skb, fcb_length); and I don't know the code well enough to know if setting the needed_headroom value _guarantees_ the above fcb_length comparison will always be false, and hence can be deleted. It kind of looks like it via LL_RESERVED_SPACE, but I'm not 100% sure... Thanks, Paul. --
quoted hunk ↗ jump to hunk
drivers/net/ethernet/freescale/gianfar.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index f2db8fc..ab1d80f 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c@@ -2063,10 +2063,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - /* Steal sock reference for processing TX time stamps */ - swap(skb_new->sk, skb->sk); - swap(skb_new->destructor, skb->destructor); - kfree_skb(skb); + if (skb->sk) + skb_set_owner_w(skb_new, skb->sk); + consume_skb(skb); skb = skb_new; }