From cf8ce1ea61b75712a154c93e40f2a5af2e4dd997 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 27 Jun 2017 17:31:49 +0300 Subject: [PATCH 1/8] ath9k: fix tx99 use after free One scenario that could lead to UAF is two threads writing simultaneously to the "tx99" debug file. One of them would set the "start" value to true and follow to ath9k_tx99_init(). Inside the function it would set the sc->tx99_state to true after allocating sc->tx99skb. Then, the other thread would execute write_file_tx99() and call ath9k_tx99_deinit(). sc->tx99_state would be freed. After that, the first thread would continue inside ath9k_tx99_init() and call r = ath9k_tx99_send(sc, sc->tx99_skb, &txctl); that would make use of the freed sc->tx99_skb memory. Cc: Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/tx99.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index a866cbda0799..49ed1afb913c 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c @@ -189,22 +189,27 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf, if (strtobool(buf, &start)) return -EINVAL; + mutex_lock(&sc->mutex); + if (start == sc->tx99_state) { if (!start) - return count; + goto out; ath_dbg(common, XMIT, "Resetting TX99\n"); ath9k_tx99_deinit(sc); } if (!start) { ath9k_tx99_deinit(sc); - return count; + goto out; } r = ath9k_tx99_init(sc); - if (r) + if (r) { + mutex_unlock(&sc->mutex); return r; - + } +out: + mutex_unlock(&sc->mutex); return count; } From bde717ab473668377fc65872398a102d40cb2d58 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 27 Jun 2017 17:31:51 +0300 Subject: [PATCH 2/8] ath9k: fix tx99 bus error The hard coded register 0x9864 and 0x9924 are invalid for ar9300 chips. Cc: Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index ae3043559b6d..fe5102ca5010 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1821,8 +1821,6 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah) static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum) { REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR); - REG_SET_BIT(ah, 0x9864, 0x7f000); - REG_SET_BIT(ah, 0x9924, 0x7f00fe); REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); REG_WRITE(ah, AR_CR, AR_CR_RXD); REG_WRITE(ah, AR_DLCL_IFS(qnum), 0); From 1cdb6c9fd43366413f928531a03fc07a8c14429a Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 27 Jun 2017 17:31:52 +0300 Subject: [PATCH 3/8] ath10k: add const to thermal_cooling_device_ops structure Declare thermal_cooling_device_ops structure as const as it is only passed as an argument to the function thermal_cooling_device_register and this argument is of type const. So, declare the structure as const. Signed-off-by: Bhumika Goyal Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c index 87948aff1bd5..ef717b631ff8 100644 --- a/drivers/net/wireless/ath/ath10k/thermal.c +++ b/drivers/net/wireless/ath/ath10k/thermal.c @@ -63,7 +63,7 @@ ath10k_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev, return 0; } -static struct thermal_cooling_device_ops ath10k_thermal_ops = { +static const struct thermal_cooling_device_ops ath10k_thermal_ops = { .get_max_state = ath10k_thermal_get_max_throttle_state, .get_cur_state = ath10k_thermal_get_cur_throttle_state, .set_cur_state = ath10k_thermal_set_cur_throttle_state, From 07246c115801c27652700e3679bb58661ef7ed65 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 27 Jun 2017 17:31:53 +0300 Subject: [PATCH 4/8] ath9k: fix an invalid pointer dereference in ath9k_rng_stop() The bug was triggered when do suspend/resuming continuously on Dell XPS L322X/0PJHXN version 9333 (2013) with kernel 4.12.0-041200rc4-generic. But can't reproduce on DELL E5440 + AR9300 PCIE chips. The warning is caused by accessing invalid pointer sc->rng_task. sc->rng_task is not be cleared after kthread_stop(sc->rng_task) be called in ath9k_rng_stop(). Because the kthread is stopped before ath9k_rng_kthread() be scheduled. So set sc->rng_task to null after kthread_stop(sc->rng_task) to resolve this issue. WARNING: CPU: 0 PID: 984 at linux/kernel/kthread.c:71 kthread_stop+0xf1/0x100 CPU: 0 PID: 984 Comm: NetworkManager Not tainted 4.12.0-041200rc4-generic #201706042031 Hardware name: Dell Inc. Dell System XPS L322X/0PJHXN, BIOS A09 05/15/2013 task: ffff950170fdda00 task.stack: ffffa22c01538000 RIP: 0010:kthread_stop+0xf1/0x100 RSP: 0018:ffffa22c0153b5b0 EFLAGS: 00010246 RAX: ffffffffa6257800 RBX: ffff950171b79560 RCX: 0000000000000000 RDX: 0000000080000000 RSI: 000000007fffffff RDI: ffff9500ac9a9680 RBP: ffffa22c0153b5c8 R08: 0000000000000000 R09: 0000000000000000 R10: ffffa22c0153b648 R11: ffff9501768004b8 R12: ffff9500ac9a9680 R13: ffff950171b79f70 R14: ffff950171b78780 R15: ffff9501749dc018 FS: 00007f0d6bfd5540(0000) GS:ffff95017f200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fc190161a08 CR3: 0000000232906000 CR4: 00000000001406f0 Call Trace: ath9k_rng_stop+0x1a/0x20 [ath9k] ath9k_stop+0x3b/0x1d0 [ath9k] drv_stop+0x33/0xf0 [mac80211] ieee80211_stop_device+0x43/0x50 [mac80211] ieee80211_do_stop+0x4f2/0x810 [mac80211] Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=196043 Reported-by: Giulio Genovese Tested-by: Giulio Genovese Cc: Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/rng.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c index 568b1c6c2b2b..73f46fb3e83a 100644 --- a/drivers/net/wireless/ath/ath9k/rng.c +++ b/drivers/net/wireless/ath/ath9k/rng.c @@ -120,6 +120,8 @@ void ath9k_rng_start(struct ath_softc *sc) void ath9k_rng_stop(struct ath_softc *sc) { - if (sc->rng_task) + if (sc->rng_task) { kthread_stop(sc->rng_task); + sc->rng_task = NULL; + } } From 473becac4b310dd720a0f5e07ce149a09467f1a4 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 27 Jun 2017 17:31:54 +0300 Subject: [PATCH 5/8] ath9k: avoid potential freezing during random generator read In the worst case, ath9k_rng_stop() may take 10s to stop rng kthread. The time is too long for users, use wait_event_interruptible_timeout() instead of msleep_interruptible(), wakup immediately once kthread_should_stop() is true. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/rng.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c index 73f46fb3e83a..f9d3d6eedd3c 100644 --- a/drivers/net/wireless/ath/ath9k/rng.c +++ b/drivers/net/wireless/ath/ath9k/rng.c @@ -24,6 +24,8 @@ #define ATH9K_RNG_BUF_SIZE 320 #define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 10) >> 5) /* quality: 10/32 */ +static DECLARE_WAIT_QUEUE_HEAD(rng_queue); + static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size) { int i, j; @@ -85,7 +87,9 @@ static int ath9k_rng_kthread(void *data) ATH9K_RNG_BUF_SIZE); if (unlikely(!bytes_read)) { delay = ath9k_rng_delay_get(++fail_stats); - msleep_interruptible(delay); + wait_event_interruptible_timeout(rng_queue, + kthread_should_stop(), + msecs_to_jiffies(delay)); continue; } From f23cdfb3fe8f6e3502b8aebb819edf5669c1d802 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Tue, 27 Jun 2017 17:31:55 +0300 Subject: [PATCH 6/8] ath9k: Use mutex_lock to avoid potential race in start/stop rng Move ath9k_rng_stop/ath9k_rng_start pair into critical section, use mutex_lock to void potential race accessing. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9e65d14e7b1e..8b4ac7f0a09b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -731,12 +731,12 @@ static int ath9k_start(struct ieee80211_hw *hw) spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_rng_start(sc); + mutex_unlock(&sc->mutex); ath9k_ps_restore(sc); - ath9k_rng_start(sc); - return 0; } @@ -826,10 +826,10 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath9k_deinit_channel_context(sc); - ath9k_rng_stop(sc); - mutex_lock(&sc->mutex); + ath9k_rng_stop(sc); + ath_cancel_work(sc); if (test_bit(ATH_OP_INVALID, &common->op_flags)) { From 23de57975f1467ec1987a716a27b20c1bc665309 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sun, 25 Jun 2017 22:29:32 +0100 Subject: [PATCH 7/8] ath10k: fix a bunch of spelling mistakes in messages Fix the following spelling mistakes in messages: syncronise -> synchronize unusally -> unusually addrress -> address inverval -> interval Signed-off-by: Colin Ian King Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 2 +- drivers/net/wireless/ath/ath10k/pci.c | 2 +- drivers/net/wireless/ath/ath10k/sdio.c | 4 ++-- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 4a71815490ae..55c808f03a84 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1392,7 +1392,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif) ret = ath10k_vdev_setup_sync(ar); if (ret) { - ath10k_warn(ar, "failed to syncronise setup for vdev %i: %d\n", + ath10k_warn(ar, "failed to synchronize setup for vdev %i: %d\n", arvif->vdev_id, ret); return ret; } diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 4f3f513dac4f..7ebfc409018d 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -469,7 +469,7 @@ static int ath10k_pci_wake_wait(struct ath10k *ar) while (tot_delay < PCIE_WAKE_TIMEOUT) { if (ath10k_pci_is_awake(ar)) { if (tot_delay > PCIE_WAKE_LATE_US) - ath10k_warn(ar, "device wakeup took %d ms which is unusally long, otherwise it works normally.\n", + ath10k_warn(ar, "device wakeup took %d ms which is unusually long, otherwise it works normally.\n", tot_delay / 1000); return 0; } diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 9e78fbae8413..859ed870bd97 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -1553,7 +1553,7 @@ static int ath10k_sdio_hif_diag_read(struct ath10k *ar, u32 address, void *buf, /* read the data */ ret = ath10k_sdio_read(ar, MBOX_WINDOW_DATA_ADDRESS, buf, buf_len); if (ret) { - ath10k_warn(ar, "failed to read from mbox window data addrress: %d\n", + ath10k_warn(ar, "failed to read from mbox window data address: %d\n", ret); return ret; } @@ -1592,7 +1592,7 @@ static int ath10k_sdio_hif_diag_write_mem(struct ath10k *ar, u32 address, ret = ath10k_sdio_write(ar, MBOX_WINDOW_DATA_ADDRESS, data, nbytes); if (ret) { ath10k_warn(ar, - "failed to write 0x%p to mbox window data addrress: %d\n", + "failed to write 0x%p to mbox window data address: %d\n", data, ret); return ret; } diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index f9188027a6f6..7616c1c4bbd3 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -2022,7 +2022,7 @@ ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar, arp->dest_ip4_addr = arg->dest_ip4_addr; ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr); - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d inverval %d\n", + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d interval %d\n", arg->vdev_id, arg->enabled, arg->method, arg->interval); return skb; } From 6788a3832c706c541d8a8227076eddde47446c8a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 26 Jun 2017 18:26:58 -0500 Subject: [PATCH 8/8] ath9k: remove useless variable assignment in ath_mci_intr() Value assigned to variable offset at line 551 is overwritten at line 562, before it can be used. This makes such variable assignment useless. Addresses-Coverity-ID: 1226941 Signed-off-by: Gustavo A. R. Silva Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/mci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 66596b95273f..cf23fd815211 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c @@ -548,7 +548,7 @@ void ath_mci_intr(struct ath_softc *sc) if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) { mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO; - offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET); + ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET); } if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) {