diff options
author | Ahmed S. Darwish <ahmed.darwish@valeo.com> | 2015-02-26 10:20:11 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2015-03-09 05:22:24 -0400 |
commit | deb2701cf704a2fd03a8b598bf73df3edb08818d (patch) | |
tree | a0481cbc08a3c1ac2ec0eb400b06207dffa9b39b | |
parent | b0d4724b8e4ce2a60ee4e097ec50c3759ec2090a (diff) |
can: kvaser_usb: Avoid double free on URB submission failures
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>
Cc: linux-stable <stable@vger.kernel.org>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r-- | drivers/net/can/usb/kvaser_usb.c | 20 |
1 files changed, 8 insertions, 12 deletions
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 2928f7003041..d986fe83c40d 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c | |||
@@ -787,7 +787,6 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv, | |||
787 | netdev_err(netdev, "Error transmitting URB\n"); | 787 | netdev_err(netdev, "Error transmitting URB\n"); |
788 | usb_unanchor_urb(urb); | 788 | usb_unanchor_urb(urb); |
789 | usb_free_urb(urb); | 789 | usb_free_urb(urb); |
790 | kfree(buf); | ||
791 | return err; | 790 | return err; |
792 | } | 791 | } |
793 | 792 | ||
@@ -1615,8 +1614,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, | |||
1615 | struct urb *urb; | 1614 | struct urb *urb; |
1616 | void *buf; | 1615 | void *buf; |
1617 | struct kvaser_msg *msg; | 1616 | struct kvaser_msg *msg; |
1618 | int i, err; | 1617 | int i, err, ret = NETDEV_TX_OK; |
1619 | int ret = NETDEV_TX_OK; | ||
1620 | u8 *msg_tx_can_flags = NULL; /* GCC */ | 1618 | u8 *msg_tx_can_flags = NULL; /* GCC */ |
1621 | 1619 | ||
1622 | if (can_dropped_invalid_skb(netdev, skb)) | 1620 | if (can_dropped_invalid_skb(netdev, skb)) |
@@ -1634,7 +1632,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, | |||
1634 | if (!buf) { | 1632 | if (!buf) { |
1635 | stats->tx_dropped++; | 1633 | stats->tx_dropped++; |
1636 | dev_kfree_skb(skb); | 1634 | dev_kfree_skb(skb); |
1637 | goto nobufmem; | 1635 | goto freeurb; |
1638 | } | 1636 | } |
1639 | 1637 | ||
1640 | msg = buf; | 1638 | msg = buf; |
@@ -1681,8 +1679,10 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, | |||
1681 | /* This should never happen; it implies a flow control bug */ | 1679 | /* This should never happen; it implies a flow control bug */ |
1682 | if (!context) { | 1680 | if (!context) { |
1683 | netdev_warn(netdev, "cannot find free context\n"); | 1681 | netdev_warn(netdev, "cannot find free context\n"); |
1682 | |||
1683 | kfree(buf); | ||
1684 | ret = NETDEV_TX_BUSY; | 1684 | ret = NETDEV_TX_BUSY; |
1685 | goto releasebuf; | 1685 | goto freeurb; |
1686 | } | 1686 | } |
1687 | 1687 | ||
1688 | context->priv = priv; | 1688 | context->priv = priv; |
@@ -1719,16 +1719,12 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb, | |||
1719 | else | 1719 | else |
1720 | netdev_warn(netdev, "Failed tx_urb %d\n", err); | 1720 | netdev_warn(netdev, "Failed tx_urb %d\n", err); |
1721 | 1721 | ||
1722 | goto releasebuf; | 1722 | goto freeurb; |
1723 | } | 1723 | } |
1724 | 1724 | ||
1725 | usb_free_urb(urb); | 1725 | ret = NETDEV_TX_OK; |
1726 | |||
1727 | return NETDEV_TX_OK; | ||
1728 | 1726 | ||
1729 | releasebuf: | 1727 | freeurb: |
1730 | kfree(buf); | ||
1731 | nobufmem: | ||
1732 | usb_free_urb(urb); | 1728 | usb_free_urb(urb); |
1733 | return ret; | 1729 | return ret; |
1734 | } | 1730 | } |