]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
s390/dasd: fix memleak in path handling error case
authorStefan Haberland <sth@linux.ibm.com>
Thu, 19 Dec 2019 08:43:51 +0000 (09:43 +0100)
committerKhalid Elmously <khalid.elmously@canonical.com>
Fri, 14 Feb 2020 06:00:53 +0000 (01:00 -0500)
BugLink: https://bugs.launchpad.net/bugs/1861929
[ Upstream commit 00b39f698a4f1ee897227cace2e3937fc4412270 ]

If for whatever reason the dasd_eckd_check_characteristics() function
exits after at least some paths have their configuration data
allocated those data is never freed again. In the error case the
device->private pointer is set to NULL and dasd_eckd_uncheck_device()
will exit without freeing the path data because of this NULL pointer.

Fix by calling dasd_eckd_clear_conf_data() for error cases.

Also use dasd_eckd_clear_conf_data() in dasd_eckd_uncheck_device()
to avoid code duplication.

Reported-by: Qian Cai <cai@lca.pw>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/s390/block/dasd_eckd.c

index cc1240a697ac9b271812869f6e0956f76de60583..adfd7f9791abc5afd728bf47bbd06eb1d4c6533b 100644 (file)
@@ -2076,7 +2076,7 @@ out_err2:
        dasd_free_block(device->block);
        device->block = NULL;
 out_err1:
-       kfree(private->conf_data);
+       dasd_eckd_clear_conf_data(device);
        kfree(device->private);
        device->private = NULL;
        return rc;
@@ -2085,7 +2085,6 @@ out_err1:
 static void dasd_eckd_uncheck_device(struct dasd_device *device)
 {
        struct dasd_eckd_private *private = device->private;
-       int i;
 
        if (!private)
                return;
@@ -2095,21 +2094,7 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
        private->sneq = NULL;
        private->vdsneq = NULL;
        private->gneq = NULL;
-       private->conf_len = 0;
-       for (i = 0; i < 8; i++) {
-               kfree(device->path[i].conf_data);
-               if ((__u8 *)device->path[i].conf_data ==
-                   private->conf_data) {
-                       private->conf_data = NULL;
-                       private->conf_len = 0;
-               }
-               device->path[i].conf_data = NULL;
-               device->path[i].cssid = 0;
-               device->path[i].ssid = 0;
-               device->path[i].chpid = 0;
-       }
-       kfree(private->conf_data);
-       private->conf_data = NULL;
+       dasd_eckd_clear_conf_data(device);
 }
 
 static struct dasd_ccw_req *