Re: [PATCH v7 03/19] s390/dasd: Guard sysfs discipline callbacks against unallocated private data
[email protected] Sat, 01 Aug 2026 18:29:51 +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: New issues: - [Medium] Lockless reads of `device->private` lack `READ_ONCE()`, leaving them vulnerable to compiler reloading and TOCTOU races. - [Low] A race condition between reading `private->lcu` and `private->features` allows unsupported I/O on HYPER PAV alias devices. Pre-existing issues: - [High] The patch misses a NULL pointer dereference in `dasd_eckd_pprc_enabled()` reachable via the `copy_pair` sysfs attribute. - [High] Asynchronous path event handlers unconditionally dereference `device->private` and are not canceled on initialization failure. - [High] Lockless access to `device->private` in sysfs handlers allows a use-after-free if device initialization fails. -- --- Patch [3]: [PATCH v7 03/19] s390/dasd: Guard sysfs discipline callbacks against unallocated private data --- commit ef202481581d23c8dd03c5042f532b8675ad8998 Author: Stefan Haberland <[email protected]> s390/dasd: Guard sysfs discipline callbacks against unallocated private data This commit guards several sysfs show/store handlers against unallocated device->private pointers during device initialization. Fixes: c729696bcf8b ("s390/dasd: Recognise data for ESE volumes") Cc: [email protected] > diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c > index 74fe73b5738ab..6e2fd445688cb 100644 > --- a/drivers/s390/block/dasd_eckd.c > +++ b/drivers/s390/block/dasd_eckd.c [Severity: High] This is a pre-existing issue, but does this patch miss guarding dasd_eckd_pprc_enabled()? When a device is set online, device->discipline is assigned before check_device() allocates device->private. If the copy_pair sysfs attribute is written during this window, dasd_copy_pair_store() locklessly invokes device->discipline->pprc_enabled(device): if (device->discipline->pprc_enabled) { pprc_enabled = device->discipline->pprc_enabled(device); The callback unconditionally dereferences private->rdc_data.facilities.PPRC_enabled, which seems like it could still cause a NULL pointer dereference. [Severity: High] This is also a pre-existing issue, but are asynchronous path event handlers safe from this same NULL pointer dereference? If a path event occurs while device->private is unallocated, the CIO layer triggers dasd_eckd_pe_handler() which schedules do_pe_handler_work(). Functions like dasd_eckd_read_fc_security() then unconditionally dereference private: rc = chsc_scud(private->uid.ssid, (u64 *)esm, &esm_valid); Additionally, if dasd_eckd_check_characteristics() encounters an error, its out_err1 path frees device->private but does not appear to cancel the pending pe_handler_worker workqueue, which could lead to a panic later. [Severity: High] This is another pre-existing issue, but is the lockless access to device->private safe from use-after-free if device initialization fails? While the new guards prevent NULL pointer dereferences, device->private is accessed locklessly in these handlers. If dasd_eckd_check_characteristics() encounters an error, it calls kfree(device->private). If a concurrent sysfs reader has just passed the if (!private) check, could it proceed to dereference the freed memory? [ ... ] > @@ -1831,7 +1848,11 @@ static int dasd_eckd_read_ext_pool_info(struct dasd_device *device) > static int dasd_eckd_ext_size(struct dasd_device *device) > { > struct dasd_eckd_private *private = device->private; > - struct dasd_ext_pool_sum eps = private->eps; > + struct dasd_ext_pool_sum eps; > + > + if (!private) > + return 0; > + eps = private->eps; [Severity: Medium] Should we use READ_ONCE() when assigning private from device->private? Because device->private is accessed locklessly and can be set to NULL concurrently by the error path, could the compiler optimize this by reloading the pointer from device->private after the NULL check? This might allow a TOCTOU NULL pointer dereference if it gets set to NULL between the check and the reload. > > if (!eps.flags.extent_size_valid) > return 0; [ ... ] > @@ -5935,8 +5965,11 @@ static int dasd_eckd_query_host_access(struct dasd_device *device, > struct ccw1 *ccw; > int rc; > > + if (!private) > + return -ENODEV; > + > /* not available for HYPER PAV alias devices */ > - if (!device->block && private->lcu->pav == HYPER_PAV) > + if (!device->block && private->lcu && private->lcu->pav == HYPER_PAV) [Severity: Low] Could checking private->lcu here introduce a race with the subsequent private->features check? A sysfs reader thread could read private->lcu as NULL before it is populated and bypass this abort. If preempted, check_device() could finish populating both lcu and features. When the reader resumes, it could evaluate the newly initialized features and proceed to issue the PSF command. Would this allow an unsupported command on HYPER PAV aliases? > return -EOPNOTSUPP; > > /* may not be supported by the storage server */ -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=3