aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2007-10-23 08:23:13 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-25 15:18:44 -0400
commit54d2bc068fd21bcb096660938bce7c7265613a24 (patch)
tree6808af091410fea3f2b7e7d06a9cdad322f51ce2 /drivers/usb
parent439a903a9663c0caa8094f3907ca60069d6c36e7 (diff)
USB: fix locking in idmouse
Pete caused me to lock at buggy drivers in this respect. The idmouse has a race between open and disconnect. This patch - solves the open/disconnect race - switches locking to mutexes Signed-off-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/misc/idmouse.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
index e6fd024024f5..4bcf7fb4e5da 100644
--- a/drivers/usb/misc/idmouse.c
+++ b/drivers/usb/misc/idmouse.c
@@ -66,6 +66,7 @@ static struct usb_device_id idmouse_table[] = {
66 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000) 66 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT, value, index, NULL, 0, 1000)
67 67
68MODULE_DEVICE_TABLE(usb, idmouse_table); 68MODULE_DEVICE_TABLE(usb, idmouse_table);
69static DEFINE_MUTEX(open_disc_mutex);
69 70
70/* structure to hold all of our device specific stuff */ 71/* structure to hold all of our device specific stuff */
71struct usb_idmouse { 72struct usb_idmouse {
@@ -80,7 +81,7 @@ struct usb_idmouse {
80 81
81 int open; /* if the port is open or not */ 82 int open; /* if the port is open or not */
82 int present; /* if the device is not disconnected */ 83 int present; /* if the device is not disconnected */
83 struct semaphore sem; /* locks this structure */ 84 struct mutex lock; /* locks this structure */
84 85
85}; 86};
86 87
@@ -213,13 +214,17 @@ static int idmouse_open(struct inode *inode, struct file *file)
213 if (!interface) 214 if (!interface)
214 return -ENODEV; 215 return -ENODEV;
215 216
217 mutex_lock(&open_disc_mutex);
216 /* get the device information block from the interface */ 218 /* get the device information block from the interface */
217 dev = usb_get_intfdata(interface); 219 dev = usb_get_intfdata(interface);
218 if (!dev) 220 if (!dev) {
221 mutex_unlock(&open_disc_mutex);
219 return -ENODEV; 222 return -ENODEV;
223 }
220 224
221 /* lock this device */ 225 /* lock this device */
222 down(&dev->sem); 226 mutex_lock(&dev->lock);
227 mutex_unlock(&open_disc_mutex);
223 228
224 /* check if already open */ 229 /* check if already open */
225 if (dev->open) { 230 if (dev->open) {
@@ -245,7 +250,7 @@ static int idmouse_open(struct inode *inode, struct file *file)
245error: 250error:
246 251
247 /* unlock this device */ 252 /* unlock this device */
248 up(&dev->sem); 253 mutex_unlock(&dev->lock);
249 return result; 254 return result;
250} 255}
251 256
@@ -258,12 +263,14 @@ static int idmouse_release(struct inode *inode, struct file *file)
258 if (dev == NULL) 263 if (dev == NULL)
259 return -ENODEV; 264 return -ENODEV;
260 265
266 mutex_lock(&open_disc_mutex);
261 /* lock our device */ 267 /* lock our device */
262 down(&dev->sem); 268 mutex_lock(&dev->lock);
263 269
264 /* are we really open? */ 270 /* are we really open? */
265 if (dev->open <= 0) { 271 if (dev->open <= 0) {
266 up(&dev->sem); 272 mutex_unlock(&dev->lock);
273 mutex_unlock(&open_disc_mutex);
267 return -ENODEV; 274 return -ENODEV;
268 } 275 }
269 276
@@ -271,10 +278,12 @@ static int idmouse_release(struct inode *inode, struct file *file)
271 278
272 if (!dev->present) { 279 if (!dev->present) {
273 /* the device was unplugged before the file was released */ 280 /* the device was unplugged before the file was released */
274 up(&dev->sem); 281 mutex_unlock(&dev->lock);
282 mutex_unlock(&open_disc_mutex);
275 idmouse_delete(dev); 283 idmouse_delete(dev);
276 } else { 284 } else {
277 up(&dev->sem); 285 mutex_unlock(&dev->lock);
286 mutex_unlock(&open_disc_mutex);
278 } 287 }
279 return 0; 288 return 0;
280} 289}
@@ -286,18 +295,18 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
286 int result; 295 int result;
287 296
288 /* lock this object */ 297 /* lock this object */
289 down(&dev->sem); 298 mutex_lock(&dev->lock);
290 299
291 /* verify that the device wasn't unplugged */ 300 /* verify that the device wasn't unplugged */
292 if (!dev->present) { 301 if (!dev->present) {
293 up(&dev->sem); 302 mutex_unlock(&dev->lock);
294 return -ENODEV; 303 return -ENODEV;
295 } 304 }
296 305
297 result = simple_read_from_buffer(buffer, count, ppos, 306 result = simple_read_from_buffer(buffer, count, ppos,
298 dev->bulk_in_buffer, IMGSIZE); 307 dev->bulk_in_buffer, IMGSIZE);
299 /* unlock the device */ 308 /* unlock the device */
300 up(&dev->sem); 309 mutex_unlock(&dev->lock);
301 return result; 310 return result;
302} 311}
303 312
@@ -320,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface,
320 if (dev == NULL) 329 if (dev == NULL)
321 return -ENOMEM; 330 return -ENOMEM;
322 331
323 init_MUTEX(&dev->sem); 332 mutex_init(&dev->lock);
324 dev->udev = udev; 333 dev->udev = udev;
325 dev->interface = interface; 334 dev->interface = interface;
326 335
@@ -372,24 +381,26 @@ static void idmouse_disconnect(struct usb_interface *interface)
372 381
373 /* get device structure */ 382 /* get device structure */
374 dev = usb_get_intfdata(interface); 383 dev = usb_get_intfdata(interface);
375 usb_set_intfdata(interface, NULL);
376 384
377 /* give back our minor */ 385 /* give back our minor */
378 usb_deregister_dev(interface, &idmouse_class); 386 usb_deregister_dev(interface, &idmouse_class);
379 387
380 /* lock it */ 388 mutex_lock(&open_disc_mutex);
381 down(&dev->sem); 389 usb_set_intfdata(interface, NULL);
390 /* lock the device */
391 mutex_lock(&dev->lock);
392 mutex_unlock(&open_disc_mutex);
382 393
383 /* prevent device read, write and ioctl */ 394 /* prevent device read, write and ioctl */
384 dev->present = 0; 395 dev->present = 0;
385 396
386 /* if the device is opened, idmouse_release will clean this up */ 397 /* if the device is opened, idmouse_release will clean this up */
387 if (!dev->open) { 398 if (!dev->open) {
388 up(&dev->sem); 399 mutex_unlock(&dev->lock);
389 idmouse_delete(dev); 400 idmouse_delete(dev);
390 } else { 401 } else {
391 /* unlock */ 402 /* unlock */
392 up(&dev->sem); 403 mutex_unlock(&dev->lock);
393 } 404 }
394 405
395 info("%s disconnected", DRIVER_DESC); 406 info("%s disconnected", DRIVER_DESC);