Hi,
This patch fixes the crash that occurs in the scanner driver when the
device is disconnected while it's still open and an application tries
to call write/read/ioctl. The patch is from Sergey Vlasov. It's the
simplest approach I've seen so far (without porting kobject to 2.4). I
can't get the scanner driver crashing with the patch applied even when
I tried hard.
The patch is ontop the MAX_MINOR fixed that I have just send.
Bye,
Henning
--- linux-2.4.22-pre6.maxminor//drivers/usb/scanner.c 2003-07-15 18:18:35.000000000
+0200
+++ linux-2.4.22-pre6.nofreeze/drivers/usb/scanner.c 2003-07-15 18:31:26.000000000
+0200
@@ -372,6 +372,10 @@
* scanners.
* - When checking if all minors are used don't read beyond p_scn_table
* (Sergey Vlasov).
+ * - Kfree the scn structure only after disconnect AND close have occured and
+ * check for scn->present. This avoids crashing when someone writes (reads) to
+ * the device while it's already disconnected but still open. Patch from
+ * Sergey Vlasov.
*
* TODO
* - Performance
@@ -417,6 +421,8 @@
*/
#include "scanner.h"
+static void purge_scanner(struct scn_usb_data *scn);
+
static void
irq_scanner(struct urb *urb)
{
@@ -507,28 +513,20 @@
static int
close_scanner(struct inode * inode, struct file * file)
{
- struct scn_usb_data *scn;
-
- kdev_t scn_minor;
+ struct scn_usb_data *scn = file->private_data;
- scn_minor = USB_SCN_MINOR (inode);
-
- dbg("close_scanner: scn_minor:%d", scn_minor);
-
- if (!p_scn_table[scn_minor]) {
- err("close_scanner(%d): invalid scn_minor", scn_minor);
- return -ENODEV;
- }
-
- down(&scn_mutex);
-
- scn = p_scn_table[scn_minor];
down(&(scn->sem));
scn->isopen = 0;
file->private_data = NULL;
- up(&scn_mutex);
+ if (!scn->present) {
+ /* The device was unplugged while open - need to clean up */
+ up(&(scn->sem));
+ purge_scanner(scn);
+ return 0;
+ }
+
up(&(scn->sem));
return 0;
@@ -556,6 +554,12 @@
down(&(scn->sem));
+ if (!scn->present) {
+ /* The device was unplugged while open */
+ up(&(scn->sem));
+ return -ENODEV;
+ }
+
if (!scn->bulk_out_ep) {
/* This scanner does not have a bulk-out endpoint */
up(&(scn->sem));
@@ -650,6 +654,12 @@
down(&(scn->sem));
+ if (!scn->present) {
+ /* The device was unplugged while open */
+ up(&(scn->sem));
+ return -ENODEV;
+ }
+
scn_minor = scn->scn_minor;
ibuf = scn->ibuf;
@@ -757,6 +767,12 @@
scn = file->private_data;
down(&(scn->sem));
+ if (!scn->present) {
+ /* The device was unplugged while open */
+ up(&(scn->sem));
+ return -ENODEV;
+ }
+
dev = scn->scn_dev;
switch (cmd)
@@ -1086,6 +1102,14 @@
}
static void
+purge_scanner(struct scn_usb_data *scn)
+{
+ kfree(scn->ibuf);
+ kfree(scn->obuf);
+ kfree(scn);
+}
+
+static void
disconnect_scanner(struct usb_device *dev, void *ptr)
{
struct scn_usb_data *scn = (struct scn_usb_data *) ptr;
@@ -1100,15 +1124,22 @@
usb_driver_release_interface(&scanner_driver,
&scn->scn_dev->actconfig->interface[scn->ifnum]);
- kfree(scn->ibuf);
- kfree(scn->obuf);
-
dbg("disconnect_scanner: De-allocating minor:%d", scn->scn_minor);
devfs_unregister(scn->devfs);
p_scn_table[scn->scn_minor] = NULL;
+
+ if (scn->isopen) {
+ /* The device is still open - cleanup must be delayed */
+ scn->present = 0;
+ up(&(scn->sem));
+ up(&scn_mutex);
+ return;
+ }
+
up (&(scn->sem));
- kfree (scn);
up (&scn_mutex);
+
+ purge_scanner(scn);
}
static struct
-------------------------------------------------------
This SF.Net email sponsored by: Parasoft
Error proof Web apps, automate testing & more.
Download & eval WebKing and get a free book.
www.parasoft.com/bulletproofapps1
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel