Thread (45 messages) 45 messages, 4 authors, 6d ago

Re: [PATCH 14/26] mtd: maps: vmu-flash: remove unused mdev->driver assignment

From: sashiko-bot@kernel.org
Date: 2026-07-04 06:08:49

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Dangling pointers for `fileerr_handler` and `can_unload` left on `maple_device` if `probe` fails.
- [Critical] Use-after-free of `card` structure due to dangling `mdev->callback` on probe error path.
- [High] Out-of-bounds read in `vmu_connect` when parsing device `function_data`.
- [High] NULL pointer dereference in `vmu_disconnect` if `vmu_queryblocks` fails.
--

commit aec7eca58a1d1d49c7c51af4d1d0fb848ff3245c
Author: Dmitry Torokhov [off-list ref]

mtd: maps: vmu-flash: remove unused mdev->driver assignment

This commit removes the unused assignment to mdev->driver and the now unused
mdrv variable in probe_maple_vmu. The driver field in struct maple_device is
no longer used since earlier cleanups.
quoted hunk ↗ jump to hunk
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
index 10244e6731d07..8f7028ac1b56a 100644
--- a/drivers/mtd/maps/vmu-flash.c
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -772,11 +772,9 @@ static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
 static int probe_maple_vmu(struct device *dev)
 {
 	struct maple_device *mdev = to_maple_dev(dev);
-	struct maple_driver *mdrv = to_maple_driver(dev->driver);
 
 	mdev->can_unload = vmu_can_unload;
 	mdev->fileerr_handler = vmu_file_error;
-	mdev->driver = mdrv;
 
 	return vmu_connect(mdev);
[Severity: Critical]
This is a pre-existing issue, but if vmu_connect() fails below, are these
pointers properly cleared?

If vmu_connect() fails, the probe aborts and the device is left unbound, but
the function pointers to vmu_can_unload() and vmu_file_error() remain
assigned to the persistent maple_device structure. 

If the vmu-flash module is subsequently unloaded, could a later
MAPLE_RESPONSE_FILEERR event cause the maple bus core to dereference the
now-dangling mdev->fileerr_handler pointer?
 }
While reviewing the context of this patch, I noticed a few other pre-existing
issues in the surrounding code:
static int vmu_connect(struct maple_device *mdev)
{
	unsigned long test_flash_data, basic_flash_data;
	int c, error;
	struct memcard *card;
	u32 partnum = 0;

	test_flash_data = be32_to_cpu(mdev->devinfo.function);
	/* Need to count how many bits are set - to find out which
	 * function_data element has details of the memory card
	 */
	c = hweight_long(test_flash_data);

	basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]);
[Severity: High]
This is a pre-existing issue, but does this array access risk an out-of-bounds
read?

Since test_flash_data is derived directly from the hardware packet, it could
have up to 32 bits set. If a malfunctioning device reports 0 bits or more than
3 bits set, does using c - 1 read past the bounds of the 3-element
function_data array?

[ ... ]
	/*
	* We want to trap meminfo not get cond
	* so set interval to zero, but rely on maple bus
	* driver to pass back the results of the meminfo
	*/
	maple_getcond_callback(mdev, vmu_queryblocks, 0,
		MAPLE_FUNC_MEMCARD);
[ ... ]
	error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
		MAPLE_COMMAND_GETMINFO, 2, &partnum);
	if (error) {
		dev_err(&mdev->dev, "Could not lock VMU at (%d, %d)"
			" error is 0x%X\n", mdev->port, mdev->unit, error);
		goto fail_mtd_info;
	}
	return 0;

fail_device_busy:
	kfree(card->mtd);
fail_mtd_info:
	kfree(card->parts);
fail_partitions:
	kfree(card);
fail_nomem:
	return error;
}
[Severity: Critical]
This is a pre-existing issue, but if maple_add_packet() fails, is the card
structure freed while the callback is still active?

In vmu_connect(), an asynchronous callback is registered via
maple_getcond_callback(). If a subsequent operation like maple_add_packet()
fails, the error path frees the card structure but does not clear
mdev->callback.

If a delayed or stray MAPLE_RESPONSE_DATATRF packet arrives later, could
maple_dma_handler() invoke the lingering mdev->callback, writing hardware
response data to the already freed card memory?

Regarding vmu_disconnect():

If vmu_queryblocks() fails, it branches to an error path that frees the
priv pointer and sets it to NULL:
	for (error = 0; error <= card->partition; error++) {
		kfree(((card->mtd)[error]).priv);
		((card->mtd)[error]).priv = NULL;
	}
Because the initial probe returned success, the device remains bound. When
it is eventually disconnected, vmu_disconnect() executes:
	for (x = 0; x < card->partitions; x++) {
		mpart = ((card->mtd)[x]).priv;
		mpart->mdev = NULL;
[Severity: High]
This is a pre-existing issue, but if vmu_queryblocks() encountered an
asynchronous failure earlier, will vmu_disconnect() blindly dereference a
NULL pointer here?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=14
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help