All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] usb: gadget: f_hid: do not copy_from_user() under a spinlock
@ 2026-08-17  6:11 Linkai Gong
  2026-08-17  8:39 ` Peter Korsgaard
  2026-08-17 14:46 ` David Laight
  0 siblings, 2 replies; 3+ messages in thread
From: Linkai Gong @ 2026-08-17  6:11 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Michael Zimmermann, Peter Korsgaard, Christophe JAILLET,
	John Keeping, William Wu, Marco Crivellari, Ethan Tidmore,
	Kees Cook, Chris Wulff, David Sands, linux-usb, linux-kernel,
	Linkai Gong, stable

f_hidg_get_report() already copied the report from userspace into a
new entry, then called copy_from_user() again under
get_report_spinlock. That can fault and sleep in atomic context.

Update the existing entry with memcpy() from the copy already taken.

Fixes: a139c98f760e ("USB: gadget: f_hid: Add GET_REPORT via userspace IOCTL")
Cc: stable@vger.kernel.org
Signed-off-by: Linkai Gong <gonglinkai@kylinos.cn>
---
 drivers/usb/gadget/function/f_hid.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index 3c6b43d06a6d..e4621e5a0b69 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -667,14 +667,9 @@ static int f_hidg_get_report(struct file *file, struct usb_hidg_report __user *b
 	ptr = f_hidg_search_for_report(hidg, report_id);
 
 	if (ptr) {
-		/* Report already exists in list - update it */
-		if (copy_from_user(&ptr->report_data, buffer,
-				sizeof(struct usb_hidg_report))) {
-			spin_unlock_irqrestore(&hidg->get_report_spinlock, flags);
-			ERROR(cdev, "copy_from_user error\n");
-			kfree(entry);
-			return -EINVAL;
-		}
+		/* Report already exists; data was copied before taking the lock. */
+		memcpy(&ptr->report_data, &entry->report_data,
+		       sizeof(struct usb_hidg_report));
 		kfree(entry);
 	} else {
 		/* Report does not exist in list - add it */
-- 
2.25.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] usb: gadget: f_hid: do not copy_from_user() under a spinlock
  2026-08-17  6:11 [PATCH] usb: gadget: f_hid: do not copy_from_user() under a spinlock Linkai Gong
@ 2026-08-17  8:39 ` Peter Korsgaard
  2026-08-17 14:46 ` David Laight
  1 sibling, 0 replies; 3+ messages in thread
From: Peter Korsgaard @ 2026-08-17  8:39 UTC (permalink / raw)
  To: Linkai Gong
  Cc: Greg Kroah-Hartman, Michael Zimmermann, Christophe JAILLET,
	John Keeping, William Wu, Marco Crivellari, Ethan Tidmore,
	Kees Cook, Chris Wulff, David Sands, linux-usb, linux-kernel,
	stable

>>>>> "Linkai" == Linkai Gong <gonglinkai@kylinos.cn> writes:

 > f_hidg_get_report() already copied the report from userspace into a
 > new entry, then called copy_from_user() again under
 > get_report_spinlock. That can fault and sleep in atomic context.

 > Update the existing entry with memcpy() from the copy already taken.

 > Fixes: a139c98f760e ("USB: gadget: f_hid: Add GET_REPORT via userspace IOCTL")
 > Cc: stable@vger.kernel.org
 > Signed-off-by: Linkai Gong <gonglinkai@kylinos.cn>

Acked-by: Peter Korsgaard <peter@korsgaard.com>

> ---
 >  drivers/usb/gadget/function/f_hid.c | 11 +++--------
 >  1 file changed, 3 insertions(+), 8 deletions(-)

 > diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
 > index 3c6b43d06a6d..e4621e5a0b69 100644
 > --- a/drivers/usb/gadget/function/f_hid.c
 > +++ b/drivers/usb/gadget/function/f_hid.c
 > @@ -667,14 +667,9 @@ static int f_hidg_get_report(struct file *file, struct usb_hidg_report __user *b
 >  	ptr = f_hidg_search_for_report(hidg, report_id);
 
 >  	if (ptr) {
 > -		/* Report already exists in list - update it */
 > -		if (copy_from_user(&ptr->report_data, buffer,
 > -				sizeof(struct usb_hidg_report))) {
 > -			spin_unlock_irqrestore(&hidg->get_report_spinlock, flags);
 > -			ERROR(cdev, "copy_from_user error\n");
 > -			kfree(entry);
 > -			return -EINVAL;
 > -		}
 > +		/* Report already exists; data was copied before taking the lock. */
 > +		memcpy(&ptr->report_data, &entry->report_data,
 > +		       sizeof(struct usb_hidg_report));
 >  		kfree(entry);
 >  	} else {
 >  		/* Report does not exist in list - add it */
 > -- 

 > 2.25.1


-- 
Bye, Peter Korsgaard

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] usb: gadget: f_hid: do not copy_from_user() under a spinlock
  2026-08-17  6:11 [PATCH] usb: gadget: f_hid: do not copy_from_user() under a spinlock Linkai Gong
  2026-08-17  8:39 ` Peter Korsgaard
@ 2026-08-17 14:46 ` David Laight
  1 sibling, 0 replies; 3+ messages in thread
From: David Laight @ 2026-08-17 14:46 UTC (permalink / raw)
  To: Linkai Gong
  Cc: Greg Kroah-Hartman, Michael Zimmermann, Peter Korsgaard,
	Christophe JAILLET, John Keeping, William Wu, Marco Crivellari,
	Ethan Tidmore, Kees Cook, Chris Wulff, David Sands, linux-usb,
	linux-kernel, stable

On Mon, 17 Aug 2026 14:11:41 +0800
Linkai Gong <gonglinkai@kylinos.cn> wrote:

> f_hidg_get_report() already copied the report from userspace into a
> new entry, then called copy_from_user() again under
> get_report_spinlock. That can fault and sleep in atomic context.
> 
> Update the existing entry with memcpy() from the copy already taken.
> 
> Fixes: a139c98f760e ("USB: gadget: f_hid: Add GET_REPORT via userspace IOCTL")
> Cc: stable@vger.kernel.org
> Signed-off-by: Linkai Gong <gonglinkai@kylinos.cn>
> ---
>  drivers/usb/gadget/function/f_hid.c | 11 +++--------
>  1 file changed, 3 insertions(+), 8 deletions(-)
> diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
> index 3c6b43d06a6d..e4621e5a0b69 100644
> --- a/drivers/usb/gadget/function/f_hid.c
> +++ b/drivers/usb/gadget/function/f_hid.c
> @@ -667,14 +667,9 @@ static int f_hidg_get_report(struct file *file, struct usb_hidg_report __user *b
>  	ptr = f_hidg_search_for_report(hidg, report_id);
>  
>  	if (ptr) {
> -		/* Report already exists in list - update it */
> -		if (copy_from_user(&ptr->report_data, buffer,
> -				sizeof(struct usb_hidg_report))) {
> -			spin_unlock_irqrestore(&hidg->get_report_spinlock, flags);
> -			ERROR(cdev, "copy_from_user error\n");

How about a patch to remove the ERROR() from the earlier copy_from_user()
error path?

	David

> -			kfree(entry);
> -			return -EINVAL;
> -		}
> +		/* Report already exists; data was copied before taking the lock. */
> +		memcpy(&ptr->report_data, &entry->report_data,
> +		       sizeof(struct usb_hidg_report));
>  		kfree(entry);
>  	} else {
>  		/* Report does not exist in list - add it */


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-17 14:46 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-17  6:11 [PATCH] usb: gadget: f_hid: do not copy_from_user() under a spinlock Linkai Gong
2026-08-17  8:39 ` Peter Korsgaard
2026-08-17 14:46 ` David Laight

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.