Re: [PATCH v5 17/17] s390/dasd: Read cached unit address and LSS in the CCW build path
[email protected] Fri, 31 Jul 2026 16:58:43 +0000
| Newsgroups | org.kernel.vger.linux-s390 |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: Pre-existing issues: - [High] Transient zeroing of `uid.type` disables alias device verification in lockless CCW-build paths. - [High] Concurrent sysfs write to `path_reset` triggers a Use-After-Free or NULL pointer dereference on `conf.gneq`. - [High] Concurrent `BIODASDINFO` / `BIODASDINFO2` ioctl triggers a Use-After-Free or NULL pointer dereference on `conf.data`. - [High] Concurrent execution of path event handlers and configuration reload causes memory corruption and UAF on `conf.data` and `conf.ned`. - [High] TOCTOU NULL pointer dereference in `dasd_eckd_generate_uid`. -- --- Patch [17]: [PATCH v5 17/17] s390/dasd: Read cached unit address and LSS in the CCW build path --- commit 962f258b40a4684c7ad8e7e9f2ae8c0f71efe3ff Author: Stefan Haberland <[email protected]> s390/dasd: Read cached unit address and LSS in the CCW build path This commit resolves a use-after-free in the CCW build paths by caching the unit address and LSS from conf.ned into the private device data. This prevents a race condition where the reload worker frees conf.ned while I/O requests are being built. > diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c > index eb2a2f8fac644..6548ee0c01d90 100644 > --- a/drivers/s390/block/dasd_eckd.c > +++ b/drivers/s390/block/dasd_eckd.c > @@ -588,8 +588,9 @@ static int prefix_LRE(struct ccw1 *ccw, struct PFX_eckd_data *pfxdata, > return -EINVAL; > } > pfxdata->format = format; > - pfxdata->base_address = basepriv->conf.ned->unit_addr; > - pfxdata->base_lss = basepriv->conf.ned->ID; > + /* cached copies - conf.ned may be freed under us by the reload worker */ > + pfxdata->base_address = basepriv->ned_ua; > + pfxdata->base_lss = basepriv->ned_lss; > pfxdata->validity.define_extent = 1; > > /* private uid is kept up to date, conf_data may be outdated */ [Severity: High] This is a pre-existing issue, but since this patch fixes lockless access to ned_lss and ned_ua, could a similar problem occur with uid.type? In drivers/s390/block/dasd_eckd.c, both prefix_LRE() and prepare_itcw() read startpriv->uid.type locklessly during I/O submission: if (startpriv->uid.type == UA_BASE_PAV_ALIAS) pfxdata->validity.verify_base = 1; Concurrently, a configuration reload calls create_uid() under ccwdev_lock, which executes memset(uid, 0, sizeof(struct dasd_uid)). Could this transient zeroing of the uid structure disable alias device verification during these CCW-build paths? [ ... ] > @@ -806,6 +807,9 @@ static int dasd_eckd_generate_uid(struct dasd_device *device) > return -ENODEV; > spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); > create_uid(&private->conf, &private->uid); > + /* cache LSS and unit address for the lockless CCW-build path */ > + private->ned_lss = private->conf.ned->ID; > + private->ned_ua = private->conf.ned->unit_addr; > spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); > return 0; > } [Severity: High] This isn't a bug introduced by this patch, but looking at the earlier checks in dasd_eckd_generate_uid() in drivers/s390/block/dasd_eckd.c, there appears to be a potential Time-of-Check to Time-of-Use race: if (!private->conf.ned || !private->conf.gneq) return -ENODEV; spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); create_uid(&private->conf, &private->uid); /* cache LSS and unit address for the lockless CCW-build path */ private->ned_lss = private->conf.ned->ID; Since the NULL check for private->conf.ned happens outside the ccwdev_lock, could a concurrent reconfiguration (like in dasd_eckd_identify_conf_parts()) locklessly set conf->ned to NULL? If so, would this result in a NULL pointer dereference when it is subsequently used inside create_uid() or when caching private->ned_lss? [ ... ] While reviewing the fixes for conf.ned, I noticed a few other pre-existing synchronization issues related to configuration reloads and path events in drivers/s390/block/dasd_eckd.c. [Severity: High] This is a pre-existing issue, but is there a potential use-after-free in get_fcx_max_data() during a concurrent sysfs path_reset? When dasd_eckd_clear_conf_data() frees device->path[i].conf_data, it appears to leave private->conf.gneq pointing to the freed memory. Could a concurrent sysfs write to path_reset call get_fcx_max_data() and locklessly read private->conf.gneq->reserved2[7], dereferencing the dangling pointer? [Severity: High] This isn't a bug introduced by this patch, but does the BIODASDINFO ioctl have a similar race with device reloads? Looking at dasd_eckd_fill_info(), it locklessly reads private->conf.len and performs a memcpy() from private->conf.data. If the reload worker calls dasd_eckd_clear_conf_data() concurrently, it frees the underlying buffer and sets conf.data = NULL. Could the ioctl thread read a non-zero length but execute the memcpy() after the buffer is freed or NULLed, leading to a crash or a memory leak to userspace? [Severity: High] This is a pre-existing issue, but is there a lack of mutual exclusion between path event handlers and configuration reloads? The do_pe_handler_work() and do_reload_device() workers might execute concurrently. If do_reload_device() calls dasd_eckd_clear_conf_data(), could rebuild_device_uid() in the PE handler concurrently execute a lockless memcpy() into the freed private->conf.data? Would it then call dasd_eckd_generate_uid(), which dereferences the dangling conf.ned pointer? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=17