Re: [PATCH v7 04/19] s390/dasd: Snapshot intrc before freeing the request block
[email protected] Sat, 01 Aug 2026 18:18:52 +0000
| Newsgroups | org.kernel.vger.linux-s390 |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: Pre-existing issues: - [High] Accessing `req->q` after the request has been freed by `blk_mq_end_request()`. - [High] Accessing `req` inside `free_cp()` after it has been requeued to the block layer in `dasd_generic_requeue_all_requests()`. - [High] `cqr->dq` is dereferenced after `cqr` is freed in `dasd_flush_block_queue()`. -- --- Patch [4]: [PATCH v7 04/19] s390/dasd: Snapshot intrc before freeing the request block --- commit 0c9b1e836f68d2761aa0c36acf690d7404a26d86 Author: Stefan Haberland <[email protected]> s390/dasd: Snapshot intrc before freeing the request block __dasd_cleanup_cqr() maps the completion result to a block status by reading cqr->intrc, but only after discipline->free_cp() has returned the request block to its memory pool. On SMP another CPU can reallocate that block and overwrite cqr->intrc before it is read, completing the request with the wrong error. This patch snapshots intrc before free_cp() is called. > diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c > index dbe3caa1e0b4a..f5585c549e09e 100644 > --- a/drivers/s390/block/dasd.c > +++ b/drivers/s390/block/dasd.c > @@ -2687,17 +2687,23 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) > struct request *req; > blk_status_t error = BLK_STS_OK; > unsigned int proc_bytes; > - int status; > + int status, intrc; > > req = (struct request *) cqr->callback_data; > dasd_profile_end(cqr->block, cqr, req); > > + /* > + * free_cp() returns the request block to its memory pool, so snapshot > + * everything still needed from cqr before calling it - another CPU can > + * reallocate and overwrite the block right after. > + */ > proc_bytes = cqr->proc_bytes; > + intrc = cqr->intrc; > status = cqr->block->base->discipline->free_cp(cqr, req); > if (status < 0) > error = errno_to_blk_status(status); > else if (status == 0) { > - switch (cqr->intrc) { > + switch (intrc) { > case -EPERM: > /* > * DASD doesn't implement SCSI/NVMe reservations, but it [Severity: High] This isn't a bug introduced by this patch, but further down in __dasd_cleanup_cqr() we have: if (error) { blk_mq_end_request(req, error); blk_mq_run_hw_queues(req->q, true); Is it safe to dereference req->q here? Once blk_mq_end_request() completes and frees the request back to the block layer's tag pool, could another thread reallocate and modify req before we access req->q? The same pattern also appears in dasd_request_done(): blk_mq_end_request(req, 0); blk_mq_run_hw_queues(req->q, true); [Severity: High] This is a pre-existing issue, but in dasd_flush_block_queue(): spin_lock_irqsave(&cqr->dq->lock, flags); cqr->endclk = get_tod_clock(); list_del_init(&cqr->blocklist); __dasd_cleanup_cqr(cqr); spin_unlock_irqrestore(&cqr->dq->lock, flags); Since __dasd_cleanup_cqr(cqr) calls free_cp() which returns cqr to its memory pool, is it safe to evaluate cqr->dq in the spin_unlock_irqrestore() call right after? If another CPU reallocates and overwrites cqr in the meantime, could cqr->dq evaluate to NULL or point to unrelated memory causing lock corruption? [Severity: High] This is a pre-existing issue, but looking at dasd_generic_requeue_all_requests(): _dasd_requeue_request(cqr); list_del_init(&cqr->blocklist); cqr->block->base->discipline->free_cp( cqr, (struct request *) cqr->callback_data); Since _dasd_requeue_request() passes ownership of the request back to the block layer, could the block layer immediately dispatch and complete it? If so, is it safe to pass req to free_cp() where it might iterate over the request's bios via rq_for_each_segment() and potentially copy bounce buffers? Could req be freed or its bios concurrently modified by the block layer before free_cp() completes? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=4