From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jason Wang Subject: [PATCH net] virtio-net: fix page refcnt leaking when fail to allocate frag skb Date: Tue, 19 Nov 2013 16:05:07 +0800 Message-ID: <1384848307-7217-1-git-send-email-jasowang@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: virtualization-bounces@lists.linux-foundation.org Errors-To: virtualization-bounces@lists.linux-foundation.org To: rusty@rustcorp.com.au, mst@redhat.com, virtualization@lists.linux-foundation.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Michael Dalton , Eric Dumazet List-Id: virtualization@lists.linuxfoundation.org We need to drop the refcnt of page when we fail to allocate an skb for frag list, otherwise it will be leaked. The bug was introduced by commit 2613af0ed18a11d5c566a81f9a6510b73180660a ("virtio_net: migrate mergeable rx buffers to page frag allocators"). Cc: Michael Dalton Cc: Eric Dumazet Cc: Rusty Russell Cc: Michael S. Tsirkin Signed-off-by: Jason Wang --- The patch was needed for 3.12 stable. --- drivers/net/virtio_net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 69ad42b..3798517 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -322,9 +322,11 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) head_skb->dev->name); len = MERGE_BUFFER_LEN; } + page = virt_to_head_page(buf); if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC); if (unlikely(!nskb)) { + put_page(page); head_skb->dev->stats.rx_dropped++; return -ENOMEM; } @@ -341,7 +343,6 @@ static int receive_mergeable(struct receive_queue *rq, struct sk_buff *head_skb) head_skb->len += len; head_skb->truesize += MERGE_BUFFER_LEN; } - page = virt_to_head_page(buf); offset = buf - (char *)page_address(page); if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { put_page(page); -- 1.8.3.2