]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.18.14/dm-mpath-fix-attached_handler_name-leak-and-dangling-hw_handler_name-pointer.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.18.14 / dm-mpath-fix-attached_handler_name-leak-and-dangling-hw_handler_name-pointer.patch
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
5
6 From: Mike Snitzer <snitzer@redhat.com>
7
8 commit b592211c33f745af67a3271ce77c10fc1e6d6241 upstream.
9
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
13 m->hw_handler_name
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
16 -EBUSY.
17
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()
21 will kfree() it.
22
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>
28
29 ---
30 drivers/md/dm-mpath.c | 14 ++++++++------
31 1 file changed, 8 insertions(+), 6 deletions(-)
32
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
36 }
37
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)
41 {
42 struct request_queue *q = bdev_get_queue(bdev);
43 int r;
44
45 if (test_bit(MPATHF_RETAIN_ATTACHED_HW_HANDLER, &m->flags)) {
46 retain:
47 - if (attached_handler_name) {
48 + if (*attached_handler_name) {
49 /*
50 * Clear any hw_handler_params associated with a
51 * handler that isn't already attached.
52 */
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;
57 }
58 @@ -830,7 +830,8 @@ retain:
59 * handler instead of the original table passed in.
60 */
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;
65 }
66 }
67
68 @@ -867,7 +868,7 @@ static struct pgpath *parse_path(struct
69 struct pgpath *p;
70 struct multipath *m = ti->private;
71 struct request_queue *q;
72 - const char *attached_handler_name;
73 + const char *attached_handler_name = NULL;
74
75 /* we need at least a path arg */
76 if (as->argc < 1) {
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);
83 if (r) {
84 dm_put_device(ti, p->path.dev);
85 goto bad;
86 @@ -905,6 +906,7 @@ static struct pgpath *parse_path(struct
87
88 return p;
89 bad:
90 + kfree(attached_handler_name);
91 free_pgpath(p);
92 return ERR_PTR(r);
93 }