]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.19.32/scsi-ibmvscsi-fix-empty-event-pool-access-during-host-removal.patch
Linux 4.14.109
[thirdparty/kernel/stable-queue.git] / releases / 4.19.32 / scsi-ibmvscsi-fix-empty-event-pool-access-during-host-removal.patch
1 From 7f5203c13ba8a7b7f9f6ecfe5a4d5567188d7835 Mon Sep 17 00:00:00 2001
2 From: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
3 Date: Wed, 20 Mar 2019 13:41:51 -0500
4 Subject: scsi: ibmvscsi: Fix empty event pool access during host removal
5
6 From: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
7
8 commit 7f5203c13ba8a7b7f9f6ecfe5a4d5567188d7835 upstream.
9
10 The event pool used for queueing commands is destroyed fairly early in the
11 ibmvscsi_remove() code path. Since, this happens prior to the call so
12 scsi_remove_host() it is possible for further calls to queuecommand to be
13 processed which manifest as a panic due to a NULL pointer dereference as
14 seen here:
15
16 PANIC: "Unable to handle kernel paging request for data at address
17 0x00000000"
18
19 Context process backtrace:
20
21 DSISR: 0000000042000000 ????Syscall Result: 0000000000000000
22 4 [c000000002cb3820] memcpy_power7 at c000000000064204
23 [Link Register] [c000000002cb3820] ibmvscsi_send_srp_event at d000000003ed14a4
24 5 [c000000002cb3920] ibmvscsi_send_srp_event at d000000003ed14a4 [ibmvscsi] ?(unreliable)
25 6 [c000000002cb39c0] ibmvscsi_queuecommand at d000000003ed2388 [ibmvscsi]
26 7 [c000000002cb3a70] scsi_dispatch_cmd at d00000000395c2d8 [scsi_mod]
27 8 [c000000002cb3af0] scsi_request_fn at d00000000395ef88 [scsi_mod]
28 9 [c000000002cb3be0] __blk_run_queue at c000000000429860
29 10 [c000000002cb3c10] blk_delay_work at c00000000042a0ec
30 11 [c000000002cb3c40] process_one_work at c0000000000dac30
31 12 [c000000002cb3cd0] worker_thread at c0000000000db110
32 13 [c000000002cb3d80] kthread at c0000000000e3378
33 14 [c000000002cb3e30] ret_from_kernel_thread at c00000000000982c
34
35 The kernel buffer log is overfilled with this log:
36
37 [11261.952732] ibmvscsi: found no event struct in pool!
38
39 This patch reorders the operations during host teardown. Start by calling
40 the SRP transport and Scsi_Host remove functions to flush any outstanding
41 work and set the host offline. LLDD teardown follows including destruction
42 of the event pool, freeing the Command Response Queue (CRQ), and unmapping
43 any persistent buffers. The event pool destruction is protected by the
44 scsi_host lock, and the pool is purged prior of any requests for which we
45 never received a response. Finally, move the removal of the scsi host from
46 our global list to the end so that the host is easily locatable for
47 debugging purposes during teardown.
48
49 Cc: <stable@vger.kernel.org> # v2.6.12+
50 Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
51 Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
52 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
53
54 ---
55 drivers/scsi/ibmvscsi/ibmvscsi.c | 22 ++++++++++++++++------
56 1 file changed, 16 insertions(+), 6 deletions(-)
57
58 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c
59 +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
60 @@ -2296,17 +2296,27 @@ static int ibmvscsi_probe(struct vio_dev
61 static int ibmvscsi_remove(struct vio_dev *vdev)
62 {
63 struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev);
64 - spin_lock(&ibmvscsi_driver_lock);
65 - list_del(&hostdata->host_list);
66 - spin_unlock(&ibmvscsi_driver_lock);
67 - unmap_persist_bufs(hostdata);
68 + unsigned long flags;
69 +
70 + srp_remove_host(hostdata->host);
71 + scsi_remove_host(hostdata->host);
72 +
73 + purge_requests(hostdata, DID_ERROR);
74 +
75 + spin_lock_irqsave(hostdata->host->host_lock, flags);
76 release_event_pool(&hostdata->pool, hostdata);
77 + spin_unlock_irqrestore(hostdata->host->host_lock, flags);
78 +
79 ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
80 max_events);
81
82 kthread_stop(hostdata->work_thread);
83 - srp_remove_host(hostdata->host);
84 - scsi_remove_host(hostdata->host);
85 + unmap_persist_bufs(hostdata);
86 +
87 + spin_lock(&ibmvscsi_driver_lock);
88 + list_del(&hostdata->host_list);
89 + spin_unlock(&ibmvscsi_driver_lock);
90 +
91 scsi_host_put(hostdata->host);
92
93 return 0;