Skip to content

Commit

Permalink
s390/dasd: fix memleak in path handling error case
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stefan Haberland authored and Jens Axboe committed Dec 20, 2019
1 parent dd4b3c8 commit 00b39f6
Showing 1 changed file with 2 additions and 17 deletions.
19 changes: 2 additions & 17 deletions drivers/s390/block/dasd_eckd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2074,7 +2074,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;
Expand All @@ -2083,7 +2083,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;
Expand All @@ -2093,21 +2092,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 *
Expand Down

0 comments on commit 00b39f6

Please sign in to comment.