Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107108888
D39373.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D39373.diff
View Options
diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h
--- a/sys/dev/usb/usb_dev.h
+++ b/sys/dev/usb/usb_dev.h
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -110,13 +110,15 @@
struct selinfo selinfo;
struct cv cv_io;
struct cv cv_drain;
+ struct sx fs_fastpath_lock;
struct usb_fifo_methods *methods;
struct usb_symlink *symlink[2];/* our symlinks */
struct proc *async_p; /* process that wants SIGIO */
struct usb_fs_endpoint *fs_ep_ptr;
struct usb_device *udev;
+#define USB_FS_XFER_MAX 126
struct usb_xfer *xfer[2];
- struct usb_xfer **fs_xfer;
+ struct usb_xfer *fs_xfer[USB_FS_XFER_MAX];
struct mtx *priv_mtx; /* client data */
/* set if FIFO is opened by a FILE: */
struct usb_cdev_privdata *curr_cpd;
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2006-2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2006-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -386,6 +386,7 @@
f = malloc(sizeof(*f), M_USBDEV, M_WAITOK | M_ZERO);
cv_init(&f->cv_io, "FIFO-IO");
cv_init(&f->cv_drain, "FIFO-DRAIN");
+ sx_init(&f->fs_fastpath_lock, "FIFO-FP");
f->priv_mtx = mtx;
f->refcount = 1;
knlist_init_mtx(&f->selinfo.si_note, mtx);
@@ -626,6 +627,7 @@
cv_destroy(&f->cv_io);
cv_destroy(&f->cv_drain);
+ sx_destroy(&f->fs_fastpath_lock);
knlist_clear(&f->selinfo.si_note, 0);
seldrain(&f->selinfo);
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008-2020 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -2829,7 +2829,7 @@
continue;
}
if ((f->dev_ep_index == 0) &&
- (f->fs_xfer == NULL)) {
+ (f->fs_ep_max == 0)) {
/* no need to free this FIFO */
continue;
}
@@ -2837,7 +2837,7 @@
if ((f->methods == &usb_ugen_methods) &&
(f->dev_ep_index == 0) &&
(!(flag & USB_UNCFG_FLAG_FREE_EP0)) &&
- (f->fs_xfer == NULL)) {
+ (f->fs_ep_max == 0)) {
/* no need to free this FIFO */
continue;
}
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -2,7 +2,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2008-2022 Hans Petter Selasky
+ * Copyright (c) 2008-2023 Hans Petter Selasky
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -968,10 +968,10 @@
int error;
/* verify input parameters */
- if (fs_ep_ptr == NULL || ep_index_max > 127)
+ if (fs_ep_ptr == NULL || ep_index_max > USB_FS_XFER_MAX)
return (EINVAL);
- if (f->fs_xfer != NULL)
+ if (f->fs_ep_max != 0)
return (EBUSY);
if (f->dev_ep_index != 0 || ep_index_max == 0)
@@ -982,11 +982,11 @@
error = usb_fifo_alloc_buffer(f, 1, ep_index_max);
if (error == 0) {
- f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) *
- ep_index_max, M_USB, M_WAITOK | M_ZERO);
+ mtx_lock(f->priv_mtx);
f->fs_ep_max = ep_index_max;
f->fs_ep_ptr = fs_ep_ptr;
f->fs_ep_sz = fs_ep_sz;
+ mtx_unlock(f->priv_mtx);
}
return (error);
}
@@ -994,15 +994,26 @@
int
ugen_fs_uninit(struct usb_fifo *f)
{
- if (f->fs_xfer == NULL) {
+ if (f->fs_ep_max == 0)
return (EINVAL);
- }
- usbd_transfer_unsetup(f->fs_xfer, f->fs_ep_max);
- free(f->fs_xfer, M_USB);
- f->fs_xfer = NULL;
+
+ /*
+ * Prevent calls into the fast-path code, by setting fs_ep_max
+ * to zero:
+ */
+ sx_xlock(&f->fs_fastpath_lock);
+ mtx_lock(f->priv_mtx);
f->fs_ep_max = 0;
+ mtx_unlock(f->priv_mtx);
+ sx_xunlock(&f->fs_fastpath_lock);
+
+ usbd_transfer_unsetup(f->fs_xfer, USB_FS_XFER_MAX);
+
+ mtx_lock(f->priv_mtx);
f->fs_ep_ptr = NULL;
f->flag_iscomplete = 0;
+ mtx_unlock(f->priv_mtx);
+
usb_fifo_free_buffer(f);
return (0);
}
@@ -1109,10 +1120,26 @@
static int
usb_fs_close(struct usb_fifo *f, struct usb_fs_close *pclose)
{
+ struct usb_xfer *xfer;
+
if (pclose->ep_index >= f->fs_ep_max)
return (EINVAL);
- usbd_transfer_unsetup(f->fs_xfer + pclose->ep_index, 1);
+ /*
+ * Prevent calls into the fast-path code, by setting the
+ * fs_xfer[] in question to NULL:
+ */
+ sx_xlock(&f->fs_fastpath_lock);
+ mtx_lock(f->priv_mtx);
+ xfer = f->fs_xfer[pclose->ep_index];
+ f->fs_xfer[pclose->ep_index] = NULL;
+ mtx_unlock(f->priv_mtx);
+ sx_xunlock(&f->fs_fastpath_lock);
+
+ if (xfer == NULL)
+ return (EINVAL);
+
+ usbd_transfer_unsetup(&xfer, 1);
return (0);
}
@@ -1249,14 +1276,16 @@
int error;
uint8_t isread;
+ mtx_lock(f->priv_mtx);
if (ep_index >= f->fs_ep_max) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
}
xfer = f->fs_xfer[ep_index];
if (xfer == NULL) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
}
- mtx_lock(f->priv_mtx);
if (usbd_transfer_pending(xfer)) {
mtx_unlock(f->priv_mtx);
return (EBUSY); /* should not happen */
@@ -1529,14 +1558,16 @@
int error;
uint8_t isread;
- if (ep_index >= f->fs_ep_max)
+ mtx_lock(f->priv_mtx);
+ if (ep_index >= f->fs_ep_max) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
-
+ }
xfer = f->fs_xfer[ep_index];
- if (xfer == NULL)
+ if (xfer == NULL) {
+ mtx_unlock(f->priv_mtx);
return (EINVAL);
-
- mtx_lock(f->priv_mtx);
+ }
if (!xfer->flags_int.transferring &&
!xfer->flags_int.started) {
mtx_unlock(f->priv_mtx);
@@ -1675,10 +1706,6 @@
struct usb_fs_complete *pcomp;
struct usb_fs_start *pstart;
struct usb_fs_stop *pstop;
- struct usb_fs_open *popen;
- struct usb_fs_open_stream *popen_stream;
- struct usb_fs_close *pclose;
- struct usb_fs_clear_stall_sync *pstall;
void *addr;
} u;
struct usb_xfer *xfer;
@@ -1691,6 +1718,7 @@
switch (cmd) {
case USB_FS_COMPLETE:
+ sx_slock(&f->fs_fastpath_lock);
mtx_lock(f->priv_mtx);
error = ugen_fs_get_complete(f, &ep_index);
mtx_unlock(f->priv_mtx);
@@ -1701,9 +1729,11 @@
u.pcomp->ep_index = ep_index;
error = ugen_fs_copy_out(f, u.pcomp->ep_index);
}
+ sx_sunlock(&f->fs_fastpath_lock);
break;
case USB_FS_START:
+ sx_slock(&f->fs_fastpath_lock);
error = ugen_fs_copy_in(f, u.pstart->ep_index);
if (error == 0) {
mtx_lock(f->priv_mtx);
@@ -1711,6 +1741,7 @@
usbd_transfer_start(xfer);
mtx_unlock(f->priv_mtx);
}
+ sx_sunlock(&f->fs_fastpath_lock);
break;
case USB_FS_STOP:
@@ -1739,20 +1770,6 @@
mtx_unlock(f->priv_mtx);
break;
- case USB_FS_OPEN:
- case USB_FS_OPEN_STREAM:
- error = usb_fs_open(f, u.popen, fflags,
- (cmd == USB_FS_OPEN_STREAM) ? u.popen_stream->stream_id : 0);
- break;
-
- case USB_FS_CLOSE:
- error = usb_fs_close(f, u.pclose);
- break;
-
- case USB_FS_CLEAR_STALL_SYNC:
- error = usb_fs_clear_stall_sync(f, u.pstall);
- break;
-
default:
error = ENOIOCTL;
break;
@@ -2212,6 +2229,10 @@
struct usb_fs_init32 *pinit32;
#endif
struct usb_fs_uninit *puninit;
+ struct usb_fs_open *popen;
+ struct usb_fs_open_stream *popen_stream;
+ struct usb_fs_close *pclose;
+ struct usb_fs_clear_stall_sync *pstall;
struct usb_device_port_path *dpp;
uint32_t *ptime;
void *addr;
@@ -2440,6 +2461,20 @@
error = ugen_fs_uninit(f);
break;
+ case USB_FS_OPEN:
+ case USB_FS_OPEN_STREAM:
+ error = usb_fs_open(f, u.popen, fflags,
+ (cmd == USB_FS_OPEN_STREAM) ? u.popen_stream->stream_id : 0);
+ break;
+
+ case USB_FS_CLOSE:
+ error = usb_fs_close(f, u.pclose);
+ break;
+
+ case USB_FS_CLEAR_STALL_SYNC:
+ error = usb_fs_clear_stall_sync(f, u.pstall);
+ break;
+
default:
mtx_lock(f->priv_mtx);
error = ugen_iface_ioctl(f, cmd, addr, fflags);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 11, 6:05 AM (18 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15751158
Default Alt Text
D39373.diff (8 KB)
Attached To
Mode
D39373: usb(4): Separate the fast path and the slow path to avoid races and use-after-free for the USB FS interface
Attached
Detach File
Event Timeline
Log In to Comment