From d11a6e4495ee1fbb38b59bc88d49d050d3736929 Mon Sep 17 00:00:00 2001 From: "Prasanna S. Panchamukhi" Date: Tue, 13 Apr 2010 16:35:58 -0700 Subject: wimax i2400m: fix race condition while accessing rx_roq by using kref count This patch fixes the race condition when one thread tries to destroy the memory allocated for rx_roq, while another thread still happen to access rx_roq. Such a race condition occurs when i2400m-sdio kernel module gets unloaded, destroying the memory allocated for rx_roq while rx_roq is accessed by i2400m_rx_edata(), as explained below: $thread1 $thread2 $ void i2400m_rx_edata() $ $Access rx_roq[] $ $roq = &i2400m->rx_roq[ro_cin] $ $ i2400m_roq_[reset/queue/update_ws] $ $ $ void i2400m_rx_release(); $ $kfree(rx->roq); $ $rx->roq = NULL; $Oops! rx_roq is NULL This patch fixes the race condition using refcount approach. Signed-off-by: Prasanna S. Panchamukhi --- drivers/net/wimax/i2400m/i2400m.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers/net/wimax/i2400m/i2400m.h') diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index 7a9c2c5b25c..b8c7dbfead4 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h @@ -412,7 +412,7 @@ struct i2400m_barker_db; * * @tx_size_max: biggest TX message sent. * - * @rx_lock: spinlock to protect RX members + * @rx_lock: spinlock to protect RX members and rx_roq_refcount. * * @rx_pl_num: total number of payloads received * @@ -436,6 +436,10 @@ struct i2400m_barker_db; * delivered. Then the driver can release them to the host. See * drivers/net/i2400m/rx.c for details. * + * @rx_roq_refcount: refcount rx_roq. This refcounts any access to + * rx_roq thus preventing rx_roq being destroyed when rx_roq + * is being accessed. rx_roq_refcount is protected by rx_lock. + * * @rx_reports: reports received from the device that couldn't be * processed because the driver wasn't still ready; when ready, * they are pulled from here and chewed. @@ -597,10 +601,12 @@ struct i2400m { tx_num, tx_size_acc, tx_size_min, tx_size_max; /* RX stuff */ - spinlock_t rx_lock; /* protect RX state */ + /* protect RX state and rx_roq_refcount */ + spinlock_t rx_lock; unsigned rx_pl_num, rx_pl_max, rx_pl_min, rx_num, rx_size_acc, rx_size_min, rx_size_max; - struct i2400m_roq *rx_roq; /* not under rx_lock! */ + struct i2400m_roq *rx_roq; /* access is refcounted */ + struct kref rx_roq_refcount; /* refcount access to rx_roq */ u8 src_mac_addr[ETH_HLEN]; struct list_head rx_reports; /* under rx_lock! */ struct work_struct rx_report_ws; -- cgit v1.2.3-70-g09d2