summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Haberland <sth@linux.ibm.com>2019-12-19 09:43:51 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-12 12:17:22 +0100
commit729a7f5e41f39973b3939733c8f88c56ebfca7a4 (patch)
treeff19a3f1ecec8429c3351842852ba9b9b61cffd4
parent000d4f2fcf2c6a6f49e50cd02cf8022e1c0caf83 (diff)
s390/dasd: fix memleak in path handling error case
[ 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>
-rw-r--r--drivers/s390/block/dasd_eckd.c19
1 files changed, 2 insertions, 17 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 108fb1c77e1d..a2e34c853ca9 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1770,7 +1770,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;
@@ -1779,7 +1779,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;
@@ -1789,21 +1788,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 *