]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
can: kvaser_usb: Avoid double free on URB submission failures
authorAhmed S. Darwish <ahmed.darwish@valeo.com>
Thu, 26 Feb 2015 15:20:11 +0000 (10:20 -0500)
committerLuis Henriques <luis.henriques@canonical.com>
Mon, 23 Mar 2015 15:16:50 +0000 (15:16 +0000)
commit deb2701cf704a2fd03a8b598bf73df3edb08818d upstream.

Upon a URB submission failure, the driver calls usb_free_urb()
but then manually frees the URB buffer by itself.  Meanwhile
usb_free_urb() has alredy freed out that transfer buffer since
we're the only code path holding a reference to this URB.

Remove two of such invalid manual free().

Signed-off-by: Ahmed S. Darwish <ahmed.darwish@valeo.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
drivers/net/can/usb/kvaser_usb.c

index 8b255e777cc710205e1bb14966a9d5fd14d30996..fa12e7cfcc958ba9e5c2d6392c1ec913df012ab3 100644 (file)
@@ -595,7 +595,6 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
                netdev_err(netdev, "Error transmitting URB\n");
                usb_unanchor_urb(urb);
                usb_free_urb(urb);
-               kfree(buf);
                return err;
        }
 
@@ -1281,8 +1280,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
        struct urb *urb;
        void *buf;
        struct kvaser_msg *msg;
-       int i, err;
-       int ret = NETDEV_TX_OK;
+       int i, err, ret = NETDEV_TX_OK;
 
        if (can_dropped_invalid_skb(netdev, skb))
                return NETDEV_TX_OK;
@@ -1299,7 +1297,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
        if (!buf) {
                stats->tx_dropped++;
                dev_kfree_skb(skb);
-               goto nobufmem;
+               goto freeurb;
        }
 
        msg = buf;
@@ -1336,8 +1334,10 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
        /* This should never happen; it implies a flow control bug */
        if (!context) {
                netdev_warn(netdev, "cannot find free context\n");
+
+               kfree(buf);
                ret =  NETDEV_TX_BUSY;
-               goto releasebuf;
+               goto freeurb;
        }
 
        context->priv = priv;
@@ -1374,16 +1374,12 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
                else
                        netdev_warn(netdev, "Failed tx_urb %d\n", err);
 
-               goto releasebuf;
+               goto freeurb;
        }
 
-       usb_free_urb(urb);
-
-       return NETDEV_TX_OK;
+       ret = NETDEV_TX_OK;
 
-releasebuf:
-       kfree(buf);
-nobufmem:
+freeurb:
        usb_free_urb(urb);
        return ret;
 }