4.4-stable review patch.  If anyone has any objections, please let me know.


From: "Guilherme G. Piccoli" <gpicc...@linux.vnet.ibm.com>

[ Upstream commit e4717292ddebcfe231651b5aff9fa19ca158d178 ]

As part of the scsi EH path, aacraid performs a reinitialization of the
adapter, which encompass freeing resources and IRQs, NULLifying lots of
pointers, and then initialize it all over again.  We've identified a
problem during the free IRQ portion of this path if CONFIG_DEBUG_SHIRQ
is enabled on kernel config file.

Happens that, in case this flag was set, right after free_irq()
effectively clears the interrupt, it checks if it was requested as
IRQF_SHARED. In positive case, it performs another call to the IRQ
handler on driver. Problem is: since aacraid currently free some
resources *before* freeing the IRQ, once free_irq() path calls the
handler again (due to CONFIG_DEBUG_SHIRQ), aacraid crashes due to NULL
pointer dereference with the following trace:

  aac_src_intr_message+0xf8/0x740 [aacraid]
  aac_free_irq+0x13c/0x150 [aacraid]
  aac_reset_adapter+0x2e8/0x970 [aacraid]
  aac_eh_reset+0x3a8/0x5d0 [aacraid]

This patch prevents the crash by changing the order of the
deinitialization in this path of aacraid: first we clear the IRQ, then
we free other resources. No functional change intended.

Signed-off-by: Guilherme G. Piccoli <gpicc...@linux.vnet.ibm.com>
Reviewed-by: Raghava Aditya Renukunta <raghavaaditya.renuku...@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.peter...@oracle.com>
Signed-off-by: Sasha Levin <alexander.le...@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>
 drivers/scsi/aacraid/commsup.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1363,13 +1363,13 @@ static int _aac_reset_adapter(struct aac
         * will ensure that i/o is queisced and the card is flushed in that
         * case.
+       aac_free_irq(aac);
        pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, 
        aac->comm_addr = NULL;
        aac->comm_phys = 0;
        aac->queues = NULL;
-       aac_free_irq(aac);
        aac->fsa_dev = NULL;
        quirks = aac_get_driver_ident(index)->quirks;

Reply via email to