]>
Commit | Line | Data |
---|---|---|
f601ab3a SL |
1 | From f2f4b368f132159c5a96b942edbf1c611dda56d3 Mon Sep 17 00:00:00 2001 |
2 | From: Logan Gunthorpe <logang@deltatee.com> | |
3 | Date: Tue, 8 Jan 2019 13:50:43 -0700 | |
4 | Subject: scsi: isci: initialize shost fully before calling scsi_add_host() | |
5 | ||
6 | [ Upstream commit cc29a1b0a3f2597ce887d339222fa85b9307706d ] | |
7 | ||
8 | scsi_mq_setup_tags(), which is called by scsi_add_host(), calculates the | |
9 | command size to allocate based on the prot_capabilities. In the isci | |
10 | driver, scsi_host_set_prot() is called after scsi_add_host() so the command | |
11 | size gets calculated to be smaller than it needs to be. Eventually, | |
12 | scsi_mq_init_request() locates the 'prot_sdb' after the command assuming it | |
13 | was sized correctly and a buffer overrun may occur. | |
14 | ||
15 | However, seeing blk_mq_alloc_rqs() rounds up to the nearest cache line | |
16 | size, the mistake can go unnoticed. | |
17 | ||
18 | The bug was noticed after the struct request size was reduced by commit | |
19 | 9d037ad707ed ("block: remove req->timeout_list") | |
20 | ||
21 | Which likely reduced the allocated space for the request by an entire cache | |
22 | line, enough that the overflow could be hit and it caused a panic, on boot, | |
23 | at: | |
24 | ||
25 | RIP: 0010:t10_pi_complete+0x77/0x1c0 | |
26 | Call Trace: | |
27 | <IRQ> | |
28 | sd_done+0xf5/0x340 | |
29 | scsi_finish_command+0xc3/0x120 | |
30 | blk_done_softirq+0x83/0xb0 | |
31 | __do_softirq+0xa1/0x2e6 | |
32 | irq_exit+0xbc/0xd0 | |
33 | call_function_single_interrupt+0xf/0x20 | |
34 | </IRQ> | |
35 | ||
36 | sd_done() would call scsi_prot_sg_count() which reads the number of | |
37 | entities in 'prot_sdb', but seeing 'prot_sdb' is located after the end of | |
38 | the allocated space it reads a garbage number and erroneously calls | |
39 | t10_pi_complete(). | |
40 | ||
41 | To prevent this, the calls to scsi_host_set_prot() are moved into | |
42 | isci_host_alloc() before the call to scsi_add_host(). Out of caution, also | |
43 | move the similar call to scsi_host_set_guard(). | |
44 | ||
45 | Fixes: 3d2d75254915 ("[SCSI] isci: T10 DIF support") | |
46 | Link: http://lkml.kernel.org/r/da851333-eadd-163a-8c78-e1f4ec5ec857@deltatee.com | |
47 | Signed-off-by: Logan Gunthorpe <logang@deltatee.com> | |
48 | Cc: Intel SCU Linux support <intel-linux-scu@intel.com> | |
49 | Cc: Artur Paszkiewicz <artur.paszkiewicz@intel.com> | |
50 | Cc: "James E.J. Bottomley" <jejb@linux.ibm.com> | |
51 | Cc: "Martin K. Petersen" <martin.petersen@oracle.com> | |
52 | Cc: Christoph Hellwig <hch@lst.de> | |
53 | Cc: Jens Axboe <axboe@kernel.dk> | |
54 | Cc: Jeff Moyer <jmoyer@redhat.com> | |
55 | Reviewed-by: Jeff Moyer <jmoyer@redhat.com> | |
56 | Reviewed-by: Jens Axboe <axboe@kernel.dk> | |
57 | Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> | |
58 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
59 | --- | |
60 | drivers/scsi/isci/init.c | 14 +++++++------- | |
61 | 1 file changed, 7 insertions(+), 7 deletions(-) | |
62 | ||
63 | diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c | |
64 | index 77128d680e3bc..6f38fa1f468a7 100644 | |
65 | --- a/drivers/scsi/isci/init.c | |
66 | +++ b/drivers/scsi/isci/init.c | |
67 | @@ -595,6 +595,13 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id) | |
68 | shost->max_lun = ~0; | |
69 | shost->max_cmd_len = MAX_COMMAND_SIZE; | |
70 | ||
71 | + /* turn on DIF support */ | |
72 | + scsi_host_set_prot(shost, | |
73 | + SHOST_DIF_TYPE1_PROTECTION | | |
74 | + SHOST_DIF_TYPE2_PROTECTION | | |
75 | + SHOST_DIF_TYPE3_PROTECTION); | |
76 | + scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); | |
77 | + | |
78 | err = scsi_add_host(shost, &pdev->dev); | |
79 | if (err) | |
80 | goto err_shost; | |
81 | @@ -682,13 +689,6 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |
82 | goto err_host_alloc; | |
83 | } | |
84 | pci_info->hosts[i] = h; | |
85 | - | |
86 | - /* turn on DIF support */ | |
87 | - scsi_host_set_prot(to_shost(h), | |
88 | - SHOST_DIF_TYPE1_PROTECTION | | |
89 | - SHOST_DIF_TYPE2_PROTECTION | | |
90 | - SHOST_DIF_TYPE3_PROTECTION); | |
91 | - scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC); | |
92 | } | |
93 | ||
94 | err = isci_setup_interrupts(pdev); | |
95 | -- | |
96 | 2.19.1 | |
97 |