]>
Commit | Line | Data |
---|---|---|
5e59985c GKH |
1 | From c9ddf73476ff4fffb7a87bd5107a0705bf2cf64b Mon Sep 17 00:00:00 2001 |
2 | From: Bart Van Assche <bart.vanassche@wdc.com> | |
3 | Date: Mon, 21 May 2018 11:17:29 -0700 | |
4 | Subject: scsi: scsi_transport_srp: Fix shost to rport translation | |
5 | ||
6 | From: Bart Van Assche <bart.vanassche@wdc.com> | |
7 | ||
8 | commit c9ddf73476ff4fffb7a87bd5107a0705bf2cf64b upstream. | |
9 | ||
10 | Since an SRP remote port is attached as a child to shost->shost_gendev | |
11 | and as the only child, the translation from the shost pointer into an | |
12 | rport pointer must happen by looking up the shost child that is an | |
13 | rport. This patch fixes the following KASAN complaint: | |
14 | ||
15 | BUG: KASAN: slab-out-of-bounds in srp_timed_out+0x57/0x110 [scsi_transport_srp] | |
16 | Read of size 4 at addr ffff880035d3fcc0 by task kworker/1:0H/19 | |
17 | ||
18 | CPU: 1 PID: 19 Comm: kworker/1:0H Not tainted 4.16.0-rc3-dbg+ #1 | |
19 | Workqueue: kblockd blk_mq_timeout_work | |
20 | Call Trace: | |
21 | dump_stack+0x85/0xc7 | |
22 | print_address_description+0x65/0x270 | |
23 | kasan_report+0x231/0x350 | |
24 | srp_timed_out+0x57/0x110 [scsi_transport_srp] | |
25 | scsi_times_out+0xc7/0x3f0 [scsi_mod] | |
26 | blk_mq_terminate_expired+0xc2/0x140 | |
27 | bt_iter+0xbc/0xd0 | |
28 | blk_mq_queue_tag_busy_iter+0x1c7/0x350 | |
29 | blk_mq_timeout_work+0x325/0x3f0 | |
30 | process_one_work+0x441/0xa50 | |
31 | worker_thread+0x76/0x6c0 | |
32 | kthread+0x1b2/0x1d0 | |
33 | ret_from_fork+0x24/0x30 | |
34 | ||
35 | Fixes: e68ca75200fe ("scsi_transport_srp: Reduce failover time") | |
36 | Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com> | |
37 | Cc: Hannes Reinecke <hare@suse.com> | |
38 | Cc: Johannes Thumshirn <jthumshirn@suse.de> | |
39 | Cc: Jason Gunthorpe <jgg@mellanox.com> | |
40 | Cc: Doug Ledford <dledford@redhat.com> | |
41 | Cc: Laurence Oberman <loberman@redhat.com> | |
42 | Cc: stable@vger.kernel.org | |
43 | Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> | |
44 | Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> | |
45 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
46 | ||
47 | --- | |
48 | drivers/scsi/scsi_transport_srp.c | 22 ++++++++++++++++++++-- | |
49 | 1 file changed, 20 insertions(+), 2 deletions(-) | |
50 | ||
51 | --- a/drivers/scsi/scsi_transport_srp.c | |
52 | +++ b/drivers/scsi/scsi_transport_srp.c | |
53 | @@ -52,6 +52,8 @@ struct srp_internal { | |
54 | struct transport_container rport_attr_cont; | |
55 | }; | |
56 | ||
57 | +static int scsi_is_srp_rport(const struct device *dev); | |
58 | + | |
59 | #define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t) | |
60 | ||
61 | #define dev_to_rport(d) container_of(d, struct srp_rport, dev) | |
62 | @@ -61,9 +63,24 @@ static inline struct Scsi_Host *rport_to | |
63 | return dev_to_shost(r->dev.parent); | |
64 | } | |
65 | ||
66 | +static int find_child_rport(struct device *dev, void *data) | |
67 | +{ | |
68 | + struct device **child = data; | |
69 | + | |
70 | + if (scsi_is_srp_rport(dev)) { | |
71 | + WARN_ON_ONCE(*child); | |
72 | + *child = dev; | |
73 | + } | |
74 | + return 0; | |
75 | +} | |
76 | + | |
77 | static inline struct srp_rport *shost_to_rport(struct Scsi_Host *shost) | |
78 | { | |
79 | - return transport_class_to_srp_rport(&shost->shost_gendev); | |
80 | + struct device *child = NULL; | |
81 | + | |
82 | + WARN_ON_ONCE(device_for_each_child(&shost->shost_gendev, &child, | |
83 | + find_child_rport) < 0); | |
84 | + return child ? dev_to_rport(child) : NULL; | |
85 | } | |
86 | ||
87 | /** | |
88 | @@ -637,7 +654,8 @@ static enum blk_eh_timer_return srp_time | |
89 | struct srp_rport *rport = shost_to_rport(shost); | |
90 | ||
91 | pr_debug("timeout for sdev %s\n", dev_name(&sdev->sdev_gendev)); | |
92 | - return rport->fast_io_fail_tmo < 0 && rport->dev_loss_tmo < 0 && | |
93 | + return rport && rport->fast_io_fail_tmo < 0 && | |
94 | + rport->dev_loss_tmo < 0 && | |
95 | i->f->reset_timer_if_blocked && scsi_device_blocked(sdev) ? | |
96 | BLK_EH_RESET_TIMER : BLK_EH_NOT_HANDLED; | |
97 | } |