| From 6c4ee863191d43c94f4af6699b4fe461e845b9b6 Mon Sep 17 00:00:00 2001 |
| From: Stefan Haberland <sth@linux.ibm.com> |
| Date: Thu, 19 Dec 2019 09:43:51 +0100 |
| Subject: [PATCH] s390/dasd: fix memleak in path handling error case |
| |
| commit 00b39f698a4f1ee897227cace2e3937fc4412270 upstream. |
| |
| 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: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c |
| index 7b1a71716b54..d9e9431747e4 100644 |
| --- a/drivers/s390/block/dasd_eckd.c |
| +++ b/drivers/s390/block/dasd_eckd.c |
| @@ -1770,7 +1770,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) |
| 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 @@ dasd_eckd_check_characteristics(struct dasd_device *device) |
| 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 * |
| -- |
| 2.7.4 |
| |