Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 729a7f5e authored by Stefan Haberland's avatar Stefan Haberland Committed by Greg Kroah-Hartman
Browse files

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: default avatarQian Cai <cai@lca.pw>
Reviewed-by: default avatarJan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: default avatarStefan Haberland <sth@linux.ibm.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 000d4f2f
Loading
Loading
Loading
Loading
+2 −17
Original line number Diff line number Diff line
@@ -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 *