staging: r8712u: Fix leak of skb
authorLarry Finger <Larry.Finger@lwfinger.net>
Sat, 4 Jun 2016 01:17:36 +0000 (20:17 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 21 Aug 2016 16:28:49 +0000 (18:28 +0200)
There are two types of messages queued for RX. The major type, which does
I/O on the device, was being handled properly. The skbs that communicated
with the firmware were being leaked.

While rewriting the code that sets up the skb, it was possible to remove
the private variable indicating that the old skb could be reused.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/rtl8712/recv_linux.c
drivers/staging/rtl8712/rtl8712_recv.h
drivers/staging/rtl8712/usb_ops_linux.c

index 735a0eadd98c013f42972036a7905a8814c14690..576c15d25a0f80a53c0891f40331400d8f0b4c47 100644 (file)
@@ -60,7 +60,6 @@ int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter,
        if (!precvbuf->purb)
                res = _FAIL;
        precvbuf->pskb = NULL;
-       precvbuf->reuse = false;
        precvbuf->pallocated_buf = NULL;
        precvbuf->pbuf = NULL;
        precvbuf->pdata = NULL;
index fd9e3fc4c226d5986a7b13715b9ae631b2c4df73..925ec746ea1544fc8f942fcb9fb6d77025823cac 100644 (file)
@@ -103,7 +103,6 @@ struct recv_buf {
        struct _adapter  *adapter;
        struct urb *purb;
        _pkt *pskb;
-       u8 reuse;
        u8  irp_pending;
        u32  transfer_len;
        uint  len;
index 0f39ea8df689b1278f1dbec92c9a07a78e019d82..fc6bb0be2a28c69c377f69d4b20c46b71a0530d2 100644 (file)
@@ -202,26 +202,23 @@ static void r8712_usb_read_port_complete(struct urb *purb)
        if (purb->status == 0) { /* SUCCESS */
                if ((purb->actual_length > (MAX_RECVBUF_SZ)) ||
                    (purb->actual_length < RXDESC_SIZE)) {
-                       precvbuf->reuse = true;
                        r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
                                  (unsigned char *)precvbuf);
                } else {
+                       _pkt *pskb = precvbuf->pskb;
+
                        precvbuf->transfer_len = purb->actual_length;
                        pbuf = (uint *)precvbuf->pbuf;
                        isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff;
                        if ((isevt & 0x1ff) == 0x1ff) {
                                r8712_rxcmd_event_hdl(padapter, pbuf);
-                               precvbuf->reuse = true;
+                               skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
                                r8712_read_port(padapter, precvpriv->ff_hwaddr,
                                                0, (unsigned char *)precvbuf);
                        } else {
-                               _pkt *pskb = precvbuf->pskb;
-
                                skb_put(pskb, purb->actual_length);
                                skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
                                tasklet_hi_schedule(&precvpriv->recv_tasklet);
-                               precvbuf->pskb = NULL;
-                               precvbuf->reuse = false;
                                r8712_read_port(padapter, precvpriv->ff_hwaddr,
                                                0, (unsigned char *)precvbuf);
                        }
@@ -241,7 +238,6 @@ static void r8712_usb_read_port_complete(struct urb *purb)
                        }
                        /* Fall through. */
                case -EPROTO:
-                       precvbuf->reuse = true;
                        r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
                                  (unsigned char *)precvbuf);
                        break;
@@ -272,14 +268,11 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
        if (adapter->bDriverStopped || adapter->bSurpriseRemoved ||
            adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf)
                return _FAIL;
-       if (precvbuf->reuse || !precvbuf->pskb) {
-               precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
-               if (precvbuf->pskb != NULL)
-                       precvbuf->reuse = true;
-       }
        r8712_init_recvbuf(adapter, precvbuf);
-       /* re-assign for linux based on skb */
-       if (!precvbuf->reuse || !precvbuf->pskb) {
+       /* Try to use skb from the free queue */
+       precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
+
+       if (!precvbuf->pskb) {
                precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev,
                                 MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
                if (!precvbuf->pskb)
@@ -293,13 +286,12 @@ u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
                precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
                precvbuf->pend = skb_end_pointer(precvbuf->pskb);
                precvbuf->pbuf = precvbuf->pskb->data;
-       } else { /* reuse skb */
+       } else { /* skb is reused */
                precvbuf->phead = precvbuf->pskb->head;
                precvbuf->pdata = precvbuf->pskb->data;
                precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
                precvbuf->pend = skb_end_pointer(precvbuf->pskb);
                precvbuf->pbuf = precvbuf->pskb->data;
-               precvbuf->reuse = false;
        }
        purb = precvbuf->purb;
        /* translate DMA FIFO addr to pipehandle */