All of lore.kernel.org
 help / color / mirror / Atom feed
From: "syzbot" <syzbot@kernel.org>
To: syzkaller-upstream-moderation@googlegroups.com
Cc: syzbot@lists.linux.dev
Subject: [PATCH RFC] usb: phy: do not overwrite dev->type in usb_add_phy_dev()
Date: Tue,  8 Sep 2026 11:05:32 +0000 (UTC)	[thread overview]
Message-ID: <36d44b2d-6fd1-4bc6-8bf6-78f1f4e9558b@mail.kernel.org> (raw)

In usb_add_phy_dev(), x->dev->type is overwritten with &usb_phy_dev_type.
However, the underlying struct device is allocated and managed by a parent
subsystem or bus driver, such as an I2C client device in phy-isp1301.
Overwriting x->dev->type clobbers the original device type (e.g.
i2c_client_type) and removes its lifecycle release callback (such as
i2c_client_dev_release).

When an I2C client device using a USB PHY is deregistered and its reference
count drops to zero, device_release() falls back to dev->type->release
since dev->release is NULL for I2C clients. Because usb_phy_dev_type does
not provide a .release callback, a warning is triggered and the memory of
the client structure is leaked:

Device '2-002c' does not have a release() function, it is broken and must
be fixed. See Documentation/core-api/kobject.rst.
WARNING: drivers/base/core.c:2643 at device_release+0x194/0x1f0
drivers/base/core.c:2642
Call Trace:
 <TASK>
 kobject_cleanup lib/kobject.c:689 [inline]
 kobject_release lib/kobject.c:720 [inline]
 kref_put include/linux/kref.h:65 [inline]
 kobject_put+0x222/0x550 lib/kobject.c:737
 i2c_deregister_clients+0x281/0x3a0 drivers/i2c/i2c-core-base.c:1783
 i2c_del_adapter+0x124/0x440 drivers/i2c/i2c-core-base.c:1827
 i2c_tiny_usb_disconnect+0x49/0xd0 drivers/i2c/busses/i2c-tiny-usb.c:282
 usb_unbind_interface+0x295/0x9f0 drivers/usb/core/driver.c:461
 device_remove drivers/base/dd.c:618 [inline]
 __device_release_driver drivers/base/dd.c:1349 [inline]
 device_release_driver_internal+0x4f5/0x880 drivers/base/dd.c:1372
 bus_remove_device+0x444/0x560 drivers/base/bus.c:664
 device_del+0x524/0x8f0 drivers/base/core.c:3965
 </TASK>

Platform devices were unaffected because platform_device_release is
assigned directly to dev->release, which device_release() checks before
dev->type->release. However, subsystems should not overwrite dev->type on
devices they do not own.

Fix this by removing usb_phy_dev_type and its assignment in
usb_add_phy_dev(). To maintain the charger uevents, construct the
environment variables directly and pass them to kobject_uevent_env() in
usb_phy_notify_charger_work().

Fixes: a8534cb092d7 ("usb: phy: introduce usb_phy device type with its own uevent handler")
Assisted-by: Gemini:gemini-3.7-flash Gemini:gemini-3.1-pro-preview syzbot
Reported-by: syzbot+3fb7629cfd12d04beeab@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=3fb7629cfd12d04beeab
Link: https://syzkaller.appspot.com/ai_job?id=313c85bd-96bf-44e8-a1a6-e25813b43afe
To: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>
To: <linux-usb@vger.kernel.org>
To: "Grzegorz Jaszczyk" <grzegorz.jaszczyk@linaro.org>
Cc: "Diogo Ivo" <diogo.ivo@tecnico.ulisboa.pt>
Cc: <linux-kernel@vger.kernel.org>

---
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 5a9b9353f..7c85c7ca1 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -42,12 +42,6 @@ static const char *const usb_chger_type[] = {
 	[ACA_TYPE]			= "USB_CHARGER_ACA_TYPE",
 };
 
-static const char *const usb_chger_state[] = {
-	[USB_CHARGER_DEFAULT]	= "USB_CHARGER_DEFAULT",
-	[USB_CHARGER_PRESENT]	= "USB_CHARGER_PRESENT",
-	[USB_CHARGER_ABSENT]	= "USB_CHARGER_ABSENT",
-};
-
 static struct usb_phy *__usb_find_phy(struct list_head *list,
 	enum usb_phy_type type)
 {
@@ -80,18 +74,6 @@ static struct usb_phy *__of_usb_find_phy(struct device_node *node)
 	return ERR_PTR(-EPROBE_DEFER);
 }
 
-static struct usb_phy *__device_to_usb_phy(const struct device *dev)
-{
-	struct usb_phy *usb_phy;
-
-	list_for_each_entry(usb_phy, &phy_list, head) {
-		if (usb_phy->dev == dev)
-			return usb_phy;
-	}
-
-	return NULL;
-}
-
 static void usb_phy_set_default_current(struct usb_phy *usb_phy)
 {
 	usb_phy->chg_cur.sdp_min = DEFAULT_SDP_CUR_MIN;
@@ -123,6 +105,9 @@ static void usb_phy_set_default_current(struct usb_phy *usb_phy)
 static void usb_phy_notify_charger_work(struct work_struct *work)
 {
 	struct usb_phy *usb_phy = container_of(work, struct usb_phy, chg_work);
+	char uchger_state[50] = { 0 };
+	char uchger_type[50] = { 0 };
+	char *envp[] = { uchger_state, uchger_type, NULL };
 	unsigned int min, max;
 
 	switch (usb_phy->chg_state) {
@@ -130,11 +115,15 @@ static void usb_phy_notify_charger_work(struct work_struct *work)
 		usb_phy_get_charger_current(usb_phy, &min, &max);
 
 		atomic_notifier_call_chain(&usb_phy->notifier, max, usb_phy);
+		snprintf(uchger_state, ARRAY_SIZE(uchger_state),
+			 "USB_CHARGER_STATE=%s", "USB_CHARGER_PRESENT");
 		break;
 	case USB_CHARGER_ABSENT:
 		usb_phy_set_default_current(usb_phy);
 
 		atomic_notifier_call_chain(&usb_phy->notifier, 0, usb_phy);
+		snprintf(uchger_state, ARRAY_SIZE(uchger_state),
+			 "USB_CHARGER_STATE=%s", "USB_CHARGER_ABSENT");
 		break;
 	default:
 		dev_warn(usb_phy->dev, "Unknown USB charger state: %d\n",
@@ -142,36 +131,9 @@ static void usb_phy_notify_charger_work(struct work_struct *work)
 		return;
 	}
 
-	kobject_uevent(&usb_phy->dev->kobj, KOBJ_CHANGE);
-}
-
-static int usb_phy_uevent(const struct device *dev, struct kobj_uevent_env *env)
-{
-	const struct usb_phy *usb_phy;
-	char uchger_state[50] = { 0 };
-	char uchger_type[50] = { 0 };
-	unsigned long flags;
-
-	spin_lock_irqsave(&phy_lock, flags);
-	usb_phy = __device_to_usb_phy(dev);
-	spin_unlock_irqrestore(&phy_lock, flags);
-
-	if (!usb_phy)
-		return -ENODEV;
-
-	snprintf(uchger_state, ARRAY_SIZE(uchger_state),
-		 "USB_CHARGER_STATE=%s", usb_chger_state[usb_phy->chg_state]);
-
 	snprintf(uchger_type, ARRAY_SIZE(uchger_type),
 		 "USB_CHARGER_TYPE=%s", usb_chger_type[usb_phy->chg_type]);
-
-	if (add_uevent_var(env, uchger_state))
-		return -ENOMEM;
-
-	if (add_uevent_var(env, uchger_type))
-		return -ENOMEM;
-
-	return 0;
+	kobject_uevent_env(&usb_phy->dev->kobj, KOBJ_CHANGE, envp);
 }
 
 static void __usb_phy_get_charger_type(struct usb_phy *usb_phy)
@@ -675,11 +637,6 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
 }
 EXPORT_SYMBOL_GPL(usb_add_phy);
 
-static const struct device_type usb_phy_dev_type = {
-	.name = "usb_phy",
-	.uevent = usb_phy_uevent,
-};
-
 /**
  * usb_add_phy_dev - declare the USB PHY
  * @x: the USB phy to be used; or NULL
@@ -705,8 +662,6 @@ int usb_add_phy_dev(struct usb_phy *x)
 	if (ret)
 		return ret;
 
-	x->dev->type = &usb_phy_dev_type;
-
 	ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
 
 	spin_lock_irqsave(&phy_lock, flags);


base-commit: df2908090cda368b01ff43709f51890076c56157
-- 
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).

See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at syzkaller@googlegroups.com.

                 reply	other threads:[~2026-09-08 11:05 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=36d44b2d-6fd1-4bc6-8bf6-78f1f4e9558b@mail.kernel.org \
    --to=syzbot@kernel.org \
    --cc=syzbot@lists.linux.dev \
    --cc=syzkaller-upstream-moderation@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.