| From 210787e82a0ac1ffb5d7be1c796f0c51050849ad Mon Sep 17 00:00:00 2001 |
| From: Stanislaw Gruszka <sgruszka@redhat.com> |
| Date: Thu, 8 Mar 2012 13:16:01 +0100 |
| Subject: iwl3945: fix possible il->txq NULL pointer dereference in delayed works |
| |
| From: Stanislaw Gruszka <sgruszka@redhat.com> |
| |
| commit 210787e82a0ac1ffb5d7be1c796f0c51050849ad upstream. |
| |
| On il3945_down procedure we free tx queue data and nullify il->txq |
| pointer. After that we drop mutex and then cancel delayed works. There |
| is possibility, that after drooping mutex and before the cancel, some |
| delayed work will start and crash while trying to send commands to |
| the device. For example, here is reported crash in |
| il3945_bg_reg_txpower_periodic(): |
| https://bugzilla.kernel.org/show_bug.cgi?id=42766#c10 |
| |
| Patch fix problem by adding il->txq check on works that send commands, |
| hence utilize tx queue. |
| |
| Reported-by: Clemens Eisserer <linuxhippy@gmail.com> |
| Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> |
| Signed-off-by: John W. Linville <linville@tuxdriver.com> |
| |
| |
| |
| --- |
| drivers/net/wireless/iwlegacy/iwl-3945.c | 7 ++++--- |
| drivers/net/wireless/iwlegacy/iwl3945-base.c | 2 +- |
| 2 files changed, 5 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/net/wireless/iwlegacy/iwl-3945.c |
| +++ b/drivers/net/wireless/iwlegacy/iwl-3945.c |
| @@ -1872,11 +1872,12 @@ static void iwl3945_bg_reg_txpower_perio |
| struct iwl_priv *priv = container_of(work, struct iwl_priv, |
| _3945.thermal_periodic.work); |
| |
| - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
| - return; |
| - |
| mutex_lock(&priv->mutex); |
| + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || priv->txq == NULL) |
| + goto out; |
| + |
| iwl3945_reg_txpower_periodic(priv); |
| +out: |
| mutex_unlock(&priv->mutex); |
| } |
| |
| --- a/drivers/net/wireless/iwlegacy/iwl3945-base.c |
| +++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c |
| @@ -2763,7 +2763,7 @@ static void iwl3945_bg_alive_start(struc |
| container_of(data, struct iwl_priv, alive_start.work); |
| |
| mutex_lock(&priv->mutex); |
| - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
| + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || priv->txq == NULL) |
| goto out; |
| |
| iwl3945_alive_start(priv); |