[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250616165321.4130714-1-dmantipov@yandex.ru>
Date: Mon, 16 Jun 2025 19:53:21 +0300
From: Dmitry Antipov <dmantipov@...dex.ru>
To: Parthiban Veerasooran <parthiban.veerasooran@...rochip.com>,
Christian Gromm <christian.gromm@...rochip.com>
Cc: linux-kernel@...r.kernel.org,
lvc-project@...uxtesting.org,
Dmitry Antipov <dmantipov@...dex.ru>
Subject: [PATCH] most: core, usb: fix generic device management
Syzkaller reports [1, 2] refcount and use-after-free errors for
the generic 'struct device' data used here and there. An overall
usage of the generic device is somewhat confusing because the
same device instance is shared between 'struct most_dev' and
'struct most_interface' instances and as a parent of the device
embedded into 'struct most_dci_obj' instance pointed from the
former. This patch hopefully fixes both of the known issues
assumes the following:
1. Direct 'mdev->iface.dev = &mdev->dev' assignment performed in
'hdm_probe()' is wrong and 'get_device()' should be used to
not break an internal reference counting.
2. To use 'get_device()' in the code above, an underlying device
should be properly initialized with 'device_initialize()'. So
'most_register_interface()' should use 'device_add()' rather
than 'device_register()'.
3. In 'hdm_disconnect()', 'put_device(&mdev->dci->dev)' is wrong
because it's done from 'device_unregister(&mdev->dci->dev)'
called from the above.
[1] https://syzkaller.appspot.com/bug?extid=d175ca7205b4f18390b1
[2] https://syzkaller.appspot.com/bug?extid=916742d5d24f6c254761
Signed-off-by: Dmitry Antipov <dmantipov@...dex.ru>
---
drivers/most/core.c | 2 +-
drivers/most/most_usb.c | 11 ++++++-----
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/most/core.c b/drivers/most/core.c
index a635d5082ebb..10951171e72d 100644
--- a/drivers/most/core.c
+++ b/drivers/most/core.c
@@ -1304,7 +1304,7 @@ int most_register_interface(struct most_interface *iface)
iface->dev->bus = &mostbus;
iface->dev->groups = interface_attr_groups;
dev_set_drvdata(iface->dev, iface);
- if (device_register(iface->dev)) {
+ if (device_add(iface->dev)) {
dev_err(iface->dev, "Failed to register interface device\n");
kfree(iface->p);
put_device(iface->dev);
diff --git a/drivers/most/most_usb.c b/drivers/most/most_usb.c
index cf5be9c449a5..3ee7abd15a09 100644
--- a/drivers/most/most_usb.c
+++ b/drivers/most/most_usb.c
@@ -973,8 +973,13 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
mdev->usb_device = usb_dev;
mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+ device_initialize(&mdev->dev);
+ mdev->dev.init_name = mdev->description;
+ mdev->dev.parent = &interface->dev;
+ mdev->dev.release = release_mdev;
+
mdev->iface.mod = hdm_usb_fops.owner;
- mdev->iface.dev = &mdev->dev;
+ mdev->iface.dev = get_device(&mdev->dev);
mdev->iface.driver_dev = &interface->dev;
mdev->iface.interface = ITYPE_USB;
mdev->iface.configure = hdm_configure_channel;
@@ -993,9 +998,6 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
usb_dev->config->desc.bConfigurationValue,
usb_iface_desc->desc.bInterfaceNumber);
- mdev->dev.init_name = mdev->description;
- mdev->dev.parent = &interface->dev;
- mdev->dev.release = release_mdev;
mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
if (!mdev->conf)
goto err_free_mdev;
@@ -1126,7 +1128,6 @@ static void hdm_disconnect(struct usb_interface *interface)
kfree(mdev->cap);
kfree(mdev->conf);
kfree(mdev->ep_address);
- put_device(&mdev->dci->dev);
put_device(&mdev->dev);
}
--
2.49.0
Powered by blists - more mailing lists