]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
usb: cdc-wdm: avoid setting WDM_READ for ZLP-s
authorRobert Hodaszi <robert.hodaszi@digi.com>
Thu, 3 Apr 2025 14:40:04 +0000 (16:40 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 6 Jul 2025 09:00:08 +0000 (11:00 +0200)
commit00626325dba74c24bf81dd95bd447fc09902a2f1
tree1177be79167bc6a9e3657c858c4e7076b49d62d1
parent433cb3e70dc95bd0641a7b4982ef07e79c14a4c9
usb: cdc-wdm: avoid setting WDM_READ for ZLP-s

[ Upstream commit 387602d8a75574fafb451b7a8215e78dfd67ee63 ]

Don't set WDM_READ flag in wdm_in_callback() for ZLP-s, otherwise when
userspace tries to poll for available data, it might - incorrectly -
believe there is something available, and when it tries to non-blocking
read it, it might get stuck in the read loop.

For example this is what glib does for non-blocking read (briefly):

  1. poll()
  2. if poll returns with non-zero, starts a read data loop:
    a. loop on poll() (EINTR disabled)
    b. if revents was set, reads data
      I. if read returns with EINTR or EAGAIN, goto 2.a.
      II. otherwise return with data

So if ZLP sets WDM_READ (#1), we expect data, and try to read it (#2).
But as that was a ZLP, and we are doing non-blocking read, wdm_read()
returns with EAGAIN (#2.b.I), so loop again, and try to read again
(#2.a.).

With glib, we might stuck in this loop forever, as EINTR is disabled
(#2.a).

Signed-off-by: Robert Hodaszi <robert.hodaszi@digi.com>
Acked-by: Oliver Neukum <oneukum@suse.com>
Link: https://lore.kernel.org/r/20250403144004.3889125-1-robert.hodaszi@digi.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/class/cdc-wdm.c