* [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference
@ 2024-01-29 9:37 Xu Yang
2024-01-29 9:37 ` [PATCH v3 2/2] usb: roles: don't get/set_role() when usb_role_switch is unregistered Xu Yang
2024-01-30 14:19 ` [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference Heikki Krogerus
0 siblings, 2 replies; 4+ messages in thread
From: Xu Yang @ 2024-01-29 9:37 UTC (permalink / raw)
To: gregkh, benjamin.tissoires, hdegoede, ivan.orlov0322,
heikki.krogerus
Cc: linux-usb, linux-imx, jun.li, stern
In current design, usb role class driver will get usb_role_switch parent's
module reference after the user get usb_role_switch device and put the
reference after the user put the usb_role_switch device. However, the
parent device of usb_role_switch may be removed before the user put the
usb_role_switch. If so, then, NULL pointer issue will be met when the user
put the parent module's reference.
This will save the module pointer in structure of usb_role_switch. Then,
we don't need to find module by iterating long relations.
Fixes: 5c54fcac9a9d ("usb: roles: Take care of driver module reference counting")
cc: <stable@vger.kernel.org>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v2:
- save module pointer as a member of usb_role_switch as suggested by Alan
Changes in v3:
- no changes
---
drivers/usb/roles/class.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index ae41578bd014..2bad038fb9ad 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -21,6 +21,7 @@ static const struct class role_class = {
struct usb_role_switch {
struct device dev;
struct mutex lock; /* device lock*/
+ struct module *module; /* the module this device depends on */
enum usb_role role;
/* From descriptor */
@@ -135,7 +136,7 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev)
usb_role_switch_match);
if (!IS_ERR_OR_NULL(sw))
- WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
+ WARN_ON(!try_module_get(sw->module));
return sw;
}
@@ -157,7 +158,7 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
sw = fwnode_connection_find_match(fwnode, "usb-role-switch",
NULL, usb_role_switch_match);
if (!IS_ERR_OR_NULL(sw))
- WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
+ WARN_ON(!try_module_get(sw->module));
return sw;
}
@@ -172,7 +173,7 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
void usb_role_switch_put(struct usb_role_switch *sw)
{
if (!IS_ERR_OR_NULL(sw)) {
- module_put(sw->dev.parent->driver->owner);
+ module_put(sw->module);
put_device(&sw->dev);
}
}
@@ -189,15 +190,18 @@ struct usb_role_switch *
usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
{
struct device *dev;
+ struct usb_role_switch *sw = NULL;
if (!fwnode)
return NULL;
dev = class_find_device_by_fwnode(&role_class, fwnode);
- if (dev)
- WARN_ON(!try_module_get(dev->parent->driver->owner));
+ if (dev) {
+ sw = to_role_switch(dev);
+ WARN_ON(!try_module_get(sw->module));
+ }
- return dev ? to_role_switch(dev) : NULL;
+ return sw;
}
EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
@@ -338,6 +342,7 @@ usb_role_switch_register(struct device *parent,
sw->set = desc->set;
sw->get = desc->get;
+ sw->module = parent->driver->owner;
sw->dev.parent = parent;
sw->dev.fwnode = desc->fwnode;
sw->dev.class = &role_class;
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH v3 2/2] usb: roles: don't get/set_role() when usb_role_switch is unregistered
2024-01-29 9:37 [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference Xu Yang
@ 2024-01-29 9:37 ` Xu Yang
2024-01-30 14:19 ` Heikki Krogerus
2024-01-30 14:19 ` [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference Heikki Krogerus
1 sibling, 1 reply; 4+ messages in thread
From: Xu Yang @ 2024-01-29 9:37 UTC (permalink / raw)
To: gregkh, benjamin.tissoires, hdegoede, ivan.orlov0322,
heikki.krogerus
Cc: linux-usb, linux-imx, jun.li, stern
There is a possibility that usb_role_switch device is unregistered before
the user put usb_role_switch. In this case, the user may still want to
get/set_role() since the user can't sense the changes of usb_role_switch.
This will add a flag to show if usb_role_switch is already registered and
avoid unwanted behaviors.
Fixes: fde0aa6c175a ("usb: common: Small class for USB role switches")
cc: <stable@vger.kernel.org>
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
---
Changes in v2:
- new patch during test patch 1
- add registered flag
Changes in v3:
- add fix tag and stable list
---
drivers/usb/roles/class.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
index 2bad038fb9ad..70165dd86b5d 100644
--- a/drivers/usb/roles/class.c
+++ b/drivers/usb/roles/class.c
@@ -23,6 +23,7 @@ struct usb_role_switch {
struct mutex lock; /* device lock*/
struct module *module; /* the module this device depends on */
enum usb_role role;
+ bool registered;
/* From descriptor */
struct device *usb2_port;
@@ -49,6 +50,9 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
if (IS_ERR_OR_NULL(sw))
return 0;
+ if (!sw->registered)
+ return -EOPNOTSUPP;
+
mutex_lock(&sw->lock);
ret = sw->set(sw, role);
@@ -74,7 +78,7 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
{
enum usb_role role;
- if (IS_ERR_OR_NULL(sw))
+ if (IS_ERR_OR_NULL(sw) || !sw->registered)
return USB_ROLE_NONE;
mutex_lock(&sw->lock);
@@ -357,6 +361,8 @@ usb_role_switch_register(struct device *parent,
return ERR_PTR(ret);
}
+ sw->registered = true;
+
/* TODO: Symlinks for the host port and the device controller. */
return sw;
@@ -371,8 +377,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_register);
*/
void usb_role_switch_unregister(struct usb_role_switch *sw)
{
- if (!IS_ERR_OR_NULL(sw))
+ if (!IS_ERR_OR_NULL(sw)) {
+ sw->registered = false;
device_unregister(&sw->dev);
+ }
}
EXPORT_SYMBOL_GPL(usb_role_switch_unregister);
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH v3 2/2] usb: roles: don't get/set_role() when usb_role_switch is unregistered
2024-01-29 9:37 ` [PATCH v3 2/2] usb: roles: don't get/set_role() when usb_role_switch is unregistered Xu Yang
@ 2024-01-30 14:19 ` Heikki Krogerus
0 siblings, 0 replies; 4+ messages in thread
From: Heikki Krogerus @ 2024-01-30 14:19 UTC (permalink / raw)
To: Xu Yang
Cc: gregkh, benjamin.tissoires, hdegoede, ivan.orlov0322, linux-usb,
linux-imx, jun.li, stern
On Mon, Jan 29, 2024 at 05:37:39PM +0800, Xu Yang wrote:
> There is a possibility that usb_role_switch device is unregistered before
> the user put usb_role_switch. In this case, the user may still want to
> get/set_role() since the user can't sense the changes of usb_role_switch.
>
> This will add a flag to show if usb_role_switch is already registered and
> avoid unwanted behaviors.
>
> Fixes: fde0aa6c175a ("usb: common: Small class for USB role switches")
> cc: <stable@vger.kernel.org>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> Changes in v2:
> - new patch during test patch 1
> - add registered flag
> Changes in v3:
> - add fix tag and stable list
> ---
> drivers/usb/roles/class.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
> index 2bad038fb9ad..70165dd86b5d 100644
> --- a/drivers/usb/roles/class.c
> +++ b/drivers/usb/roles/class.c
> @@ -23,6 +23,7 @@ struct usb_role_switch {
> struct mutex lock; /* device lock*/
> struct module *module; /* the module this device depends on */
> enum usb_role role;
> + bool registered;
>
> /* From descriptor */
> struct device *usb2_port;
> @@ -49,6 +50,9 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
> if (IS_ERR_OR_NULL(sw))
> return 0;
>
> + if (!sw->registered)
> + return -EOPNOTSUPP;
> +
> mutex_lock(&sw->lock);
>
> ret = sw->set(sw, role);
> @@ -74,7 +78,7 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw)
> {
> enum usb_role role;
>
> - if (IS_ERR_OR_NULL(sw))
> + if (IS_ERR_OR_NULL(sw) || !sw->registered)
> return USB_ROLE_NONE;
>
> mutex_lock(&sw->lock);
> @@ -357,6 +361,8 @@ usb_role_switch_register(struct device *parent,
> return ERR_PTR(ret);
> }
>
> + sw->registered = true;
> +
> /* TODO: Symlinks for the host port and the device controller. */
>
> return sw;
> @@ -371,8 +377,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_register);
> */
> void usb_role_switch_unregister(struct usb_role_switch *sw)
> {
> - if (!IS_ERR_OR_NULL(sw))
> + if (!IS_ERR_OR_NULL(sw)) {
> + sw->registered = false;
> device_unregister(&sw->dev);
> + }
> }
> EXPORT_SYMBOL_GPL(usb_role_switch_unregister);
>
> --
> 2.34.1
--
heikki
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference
2024-01-29 9:37 [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference Xu Yang
2024-01-29 9:37 ` [PATCH v3 2/2] usb: roles: don't get/set_role() when usb_role_switch is unregistered Xu Yang
@ 2024-01-30 14:19 ` Heikki Krogerus
1 sibling, 0 replies; 4+ messages in thread
From: Heikki Krogerus @ 2024-01-30 14:19 UTC (permalink / raw)
To: Xu Yang
Cc: gregkh, benjamin.tissoires, hdegoede, ivan.orlov0322, linux-usb,
linux-imx, jun.li, stern
On Mon, Jan 29, 2024 at 05:37:38PM +0800, Xu Yang wrote:
> In current design, usb role class driver will get usb_role_switch parent's
> module reference after the user get usb_role_switch device and put the
> reference after the user put the usb_role_switch device. However, the
> parent device of usb_role_switch may be removed before the user put the
> usb_role_switch. If so, then, NULL pointer issue will be met when the user
> put the parent module's reference.
>
> This will save the module pointer in structure of usb_role_switch. Then,
> we don't need to find module by iterating long relations.
>
> Fixes: 5c54fcac9a9d ("usb: roles: Take care of driver module reference counting")
> cc: <stable@vger.kernel.org>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> Changes in v2:
> - save module pointer as a member of usb_role_switch as suggested by Alan
> Changes in v3:
> - no changes
> ---
> drivers/usb/roles/class.c | 17 +++++++++++------
> 1 file changed, 11 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c
> index ae41578bd014..2bad038fb9ad 100644
> --- a/drivers/usb/roles/class.c
> +++ b/drivers/usb/roles/class.c
> @@ -21,6 +21,7 @@ static const struct class role_class = {
> struct usb_role_switch {
> struct device dev;
> struct mutex lock; /* device lock*/
> + struct module *module; /* the module this device depends on */
> enum usb_role role;
>
> /* From descriptor */
> @@ -135,7 +136,7 @@ struct usb_role_switch *usb_role_switch_get(struct device *dev)
> usb_role_switch_match);
>
> if (!IS_ERR_OR_NULL(sw))
> - WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
> + WARN_ON(!try_module_get(sw->module));
>
> return sw;
> }
> @@ -157,7 +158,7 @@ struct usb_role_switch *fwnode_usb_role_switch_get(struct fwnode_handle *fwnode)
> sw = fwnode_connection_find_match(fwnode, "usb-role-switch",
> NULL, usb_role_switch_match);
> if (!IS_ERR_OR_NULL(sw))
> - WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
> + WARN_ON(!try_module_get(sw->module));
>
> return sw;
> }
> @@ -172,7 +173,7 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
> void usb_role_switch_put(struct usb_role_switch *sw)
> {
> if (!IS_ERR_OR_NULL(sw)) {
> - module_put(sw->dev.parent->driver->owner);
> + module_put(sw->module);
> put_device(&sw->dev);
> }
> }
> @@ -189,15 +190,18 @@ struct usb_role_switch *
> usb_role_switch_find_by_fwnode(const struct fwnode_handle *fwnode)
> {
> struct device *dev;
> + struct usb_role_switch *sw = NULL;
>
> if (!fwnode)
> return NULL;
>
> dev = class_find_device_by_fwnode(&role_class, fwnode);
> - if (dev)
> - WARN_ON(!try_module_get(dev->parent->driver->owner));
> + if (dev) {
> + sw = to_role_switch(dev);
> + WARN_ON(!try_module_get(sw->module));
> + }
>
> - return dev ? to_role_switch(dev) : NULL;
> + return sw;
> }
> EXPORT_SYMBOL_GPL(usb_role_switch_find_by_fwnode);
>
> @@ -338,6 +342,7 @@ usb_role_switch_register(struct device *parent,
> sw->set = desc->set;
> sw->get = desc->get;
>
> + sw->module = parent->driver->owner;
> sw->dev.parent = parent;
> sw->dev.fwnode = desc->fwnode;
> sw->dev.class = &role_class;
> --
> 2.34.1
--
heikki
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-01-30 14:19 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-29 9:37 [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference Xu Yang
2024-01-29 9:37 ` [PATCH v3 2/2] usb: roles: don't get/set_role() when usb_role_switch is unregistered Xu Yang
2024-01-30 14:19 ` Heikki Krogerus
2024-01-30 14:19 ` [PATCH v3 1/2] usb: roles: fix NULL pointer issue when put module's reference Heikki Krogerus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).