Skip to content

Commit 952835e

Browse files
Stefan Haberlandaxboe
authored andcommitted
s390/dasd: fix use after free in dasd path handling
When new configuration data is obtained after a path event it is stored in the per path array. The old data needs to be freed. The first valid configuration data is also referenced in the device private structure to identify the device. When the old per path configuration data was freed the device still pointed to the already freed data leading to a use after free. Fix by replacing also the device configuration data with the newly obtained one before the old data gets freed. Fixes: 4601812 ("s390/dasd: Store path configuration data during path handling") Cc: [email protected] # 5.11+ Signed-off-by: Stefan Haberland <[email protected]> Reviewed-by: Jan Hoeppner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 340e845 commit 952835e

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

drivers/s390/block/dasd_eckd.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,22 +1004,31 @@ static unsigned char dasd_eckd_path_access(void *conf_data, int conf_len)
10041004
static void dasd_eckd_store_conf_data(struct dasd_device *device,
10051005
struct dasd_conf_data *conf_data, int chp)
10061006
{
1007+
struct dasd_eckd_private *private = device->private;
10071008
struct channel_path_desc_fmt0 *chp_desc;
10081009
struct subchannel_id sch_id;
1010+
void *cdp;
10091011

1010-
ccw_device_get_schid(device->cdev, &sch_id);
10111012
/*
10121013
* path handling and read_conf allocate data
10131014
* free it before replacing the pointer
1015+
* also replace the old private->conf_data pointer
1016+
* with the new one if this points to the same data
10141017
*/
1015-
kfree(device->path[chp].conf_data);
1018+
cdp = device->path[chp].conf_data;
1019+
if (private->conf_data == cdp) {
1020+
private->conf_data = (void *)conf_data;
1021+
dasd_eckd_identify_conf_parts(private);
1022+
}
1023+
ccw_device_get_schid(device->cdev, &sch_id);
10161024
device->path[chp].conf_data = conf_data;
10171025
device->path[chp].cssid = sch_id.cssid;
10181026
device->path[chp].ssid = sch_id.ssid;
10191027
chp_desc = ccw_device_get_chp_desc(device->cdev, chp);
10201028
if (chp_desc)
10211029
device->path[chp].chpid = chp_desc->chpid;
10221030
kfree(chp_desc);
1031+
kfree(cdp);
10231032
}
10241033

10251034
static void dasd_eckd_clear_conf_data(struct dasd_device *device)

0 commit comments

Comments
 (0)