[PATCH 2/3] USB speedtouch: fix memory leak in error path

From: Duncan Sands
Date: Tue Apr 13 2004 - 04:16:54 EST


Hi Greg, this patch fixes a memory leak in the speedtouch driver.
The leak occurs when the ATM layer submits a skbuff for transmission,
but the driver rejects it (because the device has been unplugged for
example). The ATM layer requires the driver to free the skbuff in this
case. The patch is against your 2.6 kernel tree.

speedtch.c | 42 +++++++++++++++++++++++++++---------------
1 files changed, 27 insertions(+), 15 deletions(-)


diff -Nru a/drivers/usb/misc/speedtch.c b/drivers/usb/misc/speedtch.c
--- a/drivers/usb/misc/speedtch.c Tue Apr 13 10:57:43 2004
+++ b/drivers/usb/misc/speedtch.c Tue Apr 13 10:57:43 2004
@@ -299,6 +299,19 @@
};


+/***********
+** misc **
+***********/
+
+static inline void udsl_pop (struct atm_vcc *vcc, struct sk_buff *skb)
+{
+ if (vcc->pop)
+ vcc->pop (vcc, skb);
+ else
+ dev_kfree_skb (skb);
+}
+
+
/*************
** decode **
*************/
@@ -720,10 +733,7 @@
if (!UDSL_SKB (skb)->num_cells) {
struct atm_vcc *vcc = UDSL_SKB (skb)->atm_data.vcc;

- if (vcc->pop)
- vcc->pop (vcc, skb);
- else
- dev_kfree_skb (skb);
+ udsl_pop (vcc, skb);
instance->current_skb = NULL;

atomic_inc (&vcc->stats->tx);
@@ -742,10 +752,7 @@
if (UDSL_SKB (skb)->atm_data.vcc == vcc) {
dbg ("udsl_cancel_send: popping skb 0x%p", skb);
__skb_unlink (skb, &instance->sndqueue);
- if (vcc->pop)
- vcc->pop (vcc, skb);
- else
- dev_kfree_skb (skb);
+ udsl_pop (vcc, skb);
}
spin_unlock_irq (&instance->sndqueue.lock);

@@ -753,10 +760,7 @@
if ((skb = instance->current_skb) && (UDSL_SKB (skb)->atm_data.vcc == vcc)) {
dbg ("udsl_cancel_send: popping current skb (0x%p)", skb);
instance->current_skb = NULL;
- if (vcc->pop)
- vcc->pop (vcc, skb);
- else
- dev_kfree_skb (skb);
+ udsl_pop (vcc, skb);
}
tasklet_enable (&instance->send_tasklet);
dbg ("udsl_cancel_send done");
@@ -765,22 +769,26 @@
static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
{
struct udsl_instance_data *instance = vcc->dev->dev_data;
+ int err;

vdbg ("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len);

if (!instance || !instance->usb_dev) {
dbg ("udsl_atm_send: NULL data!");
- return -ENODEV;
+ err = -ENODEV;
+ goto fail;
}

if (vcc->qos.aal != ATM_AAL5) {
dbg ("udsl_atm_send: unsupported ATM type %d!", vcc->qos.aal);
- return -EINVAL;
+ err = -EINVAL;
+ goto fail;
}

if (skb->len > ATM_MAX_AAL5_PDU) {
dbg ("udsl_atm_send: packet too long (%d vs %d)!", skb->len, ATM_MAX_AAL5_PDU);
- return -EINVAL;
+ err = -EINVAL;
+ goto fail;
}

PACKETDEBUG (skb->data, skb->len);
@@ -790,6 +798,10 @@
tasklet_schedule (&instance->send_tasklet);

return 0;
+
+fail:
+ udsl_pop (vcc, skb);
+ return err;
}


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/