usb/81308: Polling a ugen(4) control endpoint causes a kernel panic
Dirk Gouders
gouder at et.bocholt.gh-ge.de
Fri May 20 15:00:26 GMT 2005
>Number: 81308
>Category: usb
>Synopsis: Polling a ugen(4) control endpoint causes a kernel panic
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: freebsd-usb
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri May 20 15:00:24 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Dirk Gouders
>Release: FreeBSD 4.11-STABLE i386
>Organization:
FH Gelsenkirchen, Abt. Bocholt
>Environment:
System: FreeBSD karga.hank.home 4.11-STABLE FreeBSD 4.11-STABLE #4: Fri May 20 16:01:10 CEST 2005 root at karga.hank.home:/usr/src/sys/compile/KARGA i386
>Description:
Polling a ugen control endpoint (ugen0) causes a page fault in the
function ugenpoll().
>How-To-Repeat:
When a USB device that is handled by ugen(4) is attached, the
following program invoked with the argument /dev/ugen0 will
reproduce the kernel panic.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <poll.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int fd;
int nfd;
char *path = argv[1];
struct pollfd pfd[1];
fd = open(path, O_RDWR);
if ( fd < 0 ) {
fprintf(stderr, "%s: %s\n", path, strerror(errno));
exit(1);
}
pfd[0].fd = fd;
pfd[0].events = POLLHUP;
pfd[0].revents = 0;
nfd = poll(pfd, 1, 10);
if ( nfd < 0 ) {
fprintf(stderr, "poll(2): %s\n", strerror(errno));
exit(1);
}
if ( pfd[0].revents && POLLNVAL )
printf("POLLNVAL set in revents\n");
printf("nfd = %d\n", nfd);
close(fd);
exit(0);
}
>Fix:
I reported this problem to freebsd-hackers and Hans Petter Selasky
noted that the control endpoint does not support polling and
suggested that /sys/dev/usb/ugen.c should handle such a situation.
The attached patch works for me, although I am not sure if this
is the most elegant solution.
On a machine running 5.4-RELEASE, this problem does not occur
(poll() just returns '0') and I could not see any changes in
/sys/dev/usb/ugen.c that addresses this problem.
--- ugen.c.diff begins here ---
--- /sys/dev/usb/ugen.c.orig Tue Apr 26 09:44:44 2005
+++ /sys/dev/usb/ugen.c Fri May 20 16:26:39 2005
@@ -1421,6 +1421,10 @@
int revents = 0;
int s;
+ /* Do not allow to poll a control endpoint */
+ if ( UGENENDPOINT(dev) == USB_CONTROL_ENDPOINT )
+ return POLLNVAL;
+
USB_GET_SC(ugen, UGENUNIT(dev), sc);
if (sc->sc_dying)
--- ugen.c.diff ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-usb
mailing list