From: Michal Kazior Date: Wed, 31 Jul 2013 08:55:11 +0000 (+0200) Subject: ath10k: prevent using invalid ringbuffer indexes X-Git-Tag: v3.12-rc1~132^2~84^2^2~109^2~8 X-Git-Url: http://git.cascardo.info/?p=cascardo%2Flinux.git;a=commitdiff_plain;h=432358ed1d18c19dbf89008325ff6ba662d0996e ath10k: prevent using invalid ringbuffer indexes If the device is removed and hotplug fails ioread32() will return 0xFFFFFFFF. In that case reading ringbuffer during device bringup led to out-of-bounds addressing of a ringbuffer array that in turn led to a paging failure. This could be reproduced by the following: * boot without acpi/prevent hotplug from working * insert and manually detect (pci rescan) the device * remove the device physically * load ath10k driver * kernel crashed Ringbuffer index reading is now protected by using an appropriate mask to prevent addressing an invalid array index. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index b40792900bd5..f8b969f518f8 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -637,6 +637,7 @@ static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state, ath10k_pci_wake(ar); src_ring->hw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); + src_ring->hw_index &= nentries_mask; ath10k_pci_sleep(ar); } read_index = src_ring->hw_index; @@ -950,10 +951,12 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, ath10k_pci_wake(ar); src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); + src_ring->sw_index &= src_ring->nentries_mask; src_ring->hw_index = src_ring->sw_index; src_ring->write_index = ath10k_ce_src_ring_write_index_get(ar, ctrl_addr); + src_ring->write_index &= src_ring->nentries_mask; ath10k_pci_sleep(ar); src_ring->per_transfer_context = (void **)ptr; @@ -1035,8 +1038,10 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, ath10k_pci_wake(ar); dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); + dest_ring->sw_index &= dest_ring->nentries_mask; dest_ring->write_index = ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr); + dest_ring->write_index &= dest_ring->nentries_mask; ath10k_pci_sleep(ar); dest_ring->per_transfer_context = (void **)ptr;