1 From b592211c33f745af67a3271ce77c10fc1e6d6241 Mon Sep 17 00:00:00 2001
2 From: Mike Snitzer <snitzer@redhat.com>
3 Date: Mon, 17 Sep 2018 11:38:47 -0400
4 Subject: dm mpath: fix attached_handler_name leak and dangling hw_handler_name pointer
6 From: Mike Snitzer <snitzer@redhat.com>
8 commit b592211c33f745af67a3271ce77c10fc1e6d6241 upstream.
10 Commit e8f74a0f0011 ("dm mpath: eliminate need to use
11 scsi_device_from_queue") introduced 2 regressions:
12 1) memory leak occurs if attached_handler_name is not assigned to
14 2) m->hw_handler_name can become a dangling pointer if the
15 RETAIN_ATTACHED_HW_HANDLER flag is set and scsi_dh_attach() returns
18 Fix both of these by clearing 'attached_handler_name' pointer passed to
19 setup_scsi_dh() after it is assigned to m->hw_handler_name. And if
20 setup_scsi_dh() doesn't consume 'attached_handler_name' parse_path()
23 Fixes: e8f74a0f0011 ("dm mpath: eliminate need to use scsi_device_from_queue")
24 Cc: stable@vger.kernel.org # 4.16+
25 Reported-by: Bart Van Assche <bvanassche@acm.org>
26 Signed-off-by: Mike Snitzer <snitzer@redhat.com>
27 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
30 drivers/md/dm-mpath.c | 14 ++++++++------
31 1 file changed, 8 insertions(+), 6 deletions(-)
33 --- a/drivers/md/dm-mpath.c
34 +++ b/drivers/md/dm-mpath.c
35 @@ -806,19 +806,19 @@ static int parse_path_selector(struct dm
38 static int setup_scsi_dh(struct block_device *bdev, struct multipath *m,
39 - const char *attached_handler_name, char **error)
40 + const char **attached_handler_name, char **error)
42 struct request_queue *q = bdev_get_queue(bdev);
45 if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) {
47 - if (attached_handler_name) {
48 + if (*attached_handler_name) {
50 * Clear any hw_handler_params associated with a
51 * handler that isn't already attached.
53 - if (m->hw_handler_name && strcmp(attached_handler_name, m->hw_handler_name)) {
54 + if (m->hw_handler_name && strcmp(*attached_handler_name, m->hw_handler_name)) {
55 kfree(m->hw_handler_params);
56 m->hw_handler_params = NULL;
58 @@ -830,7 +830,8 @@ retain:
59 * handler instead of the original table passed in.
61 kfree(m->hw_handler_name);
62 - m->hw_handler_name = attached_handler_name;
63 + m->hw_handler_name = *attached_handler_name;
64 + *attached_handler_name = NULL;
68 @@ -867,7 +868,7 @@ static struct pgpath *parse_path(struct
70 struct multipath *m = ti->private;
71 struct request_queue *q;
72 - const char *attached_handler_name;
73 + const char *attached_handler_name = NULL;
75 /* we need at least a path arg */
77 @@ -890,7 +891,7 @@ static struct pgpath *parse_path(struct
78 attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
79 if (attached_handler_name || m->hw_handler_name) {
80 INIT_DELAYED_WORK(&p->activate_path, activate_path_work);
81 - r = setup_scsi_dh(p->path.dev->bdev, m, attached_handler_name, &ti->error);
82 + r = setup_scsi_dh(p->path.dev->bdev, m, &attached_handler_name, &ti->error);
84 dm_put_device(ti, p->path.dev);
86 @@ -905,6 +906,7 @@ static struct pgpath *parse_path(struct
90 + kfree(attached_handler_name);