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 | } |
