| From foo@baz Thu May 24 11:23:00 CEST 2018 |
| From: Meelis Roos <mroos@linux.ee> |
| Date: Fri, 9 Feb 2018 08:57:44 +0200 |
| Subject: scsi: aacraid: fix shutdown crash when init fails |
| |
| From: Meelis Roos <mroos@linux.ee> |
| |
| [ Upstream commit 00c20cdc79259c6c5bf978b21af96c2d3edb646d ] |
| |
| When aacraid init fails with "AAC0: adapter self-test failed.", shutdown |
| leads to UBSAN warning and then oops: |
| |
| [154316.118423] ================================================================================ |
| [154316.118508] UBSAN: Undefined behaviour in drivers/scsi/scsi_lib.c:2328:27 |
| [154316.118566] member access within null pointer of type 'struct Scsi_Host' |
| [154316.118631] CPU: 2 PID: 14530 Comm: reboot Tainted: G W 4.15.0-dirty #89 |
| [154316.118701] Hardware name: Hewlett Packard HP NetServer/HP System Board, BIOS 4.06.46 PW 06/25/2003 |
| [154316.118774] Call Trace: |
| [154316.118848] dump_stack+0x48/0x65 |
| [154316.118916] ubsan_epilogue+0xe/0x40 |
| [154316.118976] __ubsan_handle_type_mismatch+0xfb/0x180 |
| [154316.119043] scsi_block_requests+0x20/0x30 |
| [154316.119135] aac_shutdown+0x18/0x40 [aacraid] |
| [154316.119196] pci_device_shutdown+0x33/0x50 |
| [154316.119269] device_shutdown+0x18a/0x390 |
| [...] |
| [154316.123435] BUG: unable to handle kernel NULL pointer dereference at 000000f4 |
| [154316.123515] IP: scsi_block_requests+0xa/0x30 |
| |
| This is because aac_shutdown() does |
| |
| struct Scsi_Host *shost = pci_get_drvdata(dev); |
| scsi_block_requests(shost); |
| |
| and that assumes shost has been assigned with pci_set_drvdata(). |
| |
| However, pci_set_drvdata(pdev, shost) is done in aac_probe_one() far |
| after bailing out with error from calling the init function |
| ((*aac_drivers[index].init)(aac)), and when the init function fails, no |
| error is returned from aac_probe_one() so PCI layer assumes there is |
| driver attached, and tries to shut it down later. |
| |
| Fix it by returning error from aac_probe_one() when card-specific init |
| function fails. |
| |
| This fixes reboot on my HP NetRAID-4M with dead battery. |
| |
| Signed-off-by: Meelis Roos <mroos@linux.ee> |
| Reviewed-by: Dave Carroll <david.carroll@microsemi.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/scsi/aacraid/linit.c | 4 +++- |
| 1 file changed, 3 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/scsi/aacraid/linit.c |
| +++ b/drivers/scsi/aacraid/linit.c |
| @@ -1203,8 +1203,10 @@ static int aac_probe_one(struct pci_dev |
| * Map in the registers from the adapter. |
| */ |
| aac->base_size = AAC_MIN_FOOTPRINT_SIZE; |
| - if ((*aac_drivers[index].init)(aac)) |
| + if ((*aac_drivers[index].init)(aac)) { |
| + error = -ENODEV; |
| goto out_unmap; |
| + } |
| |
| if (aac->sync_mode) { |
| if (aac_sync_mode) |