aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-10-21 20:57:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-22 01:50:37 -0400
commit4a215aade0baa0487d4644d7aef6f166c84c516e (patch)
tree3cf126e431235d21fdf565e2d39089397680e803 /drivers/input
parent2f0157f13f42800aa3d9017ebb0fb80a65f7b2de (diff)
Input: fix use-after-free introduced with dynamic minor changes
Commit 7f8d4cad1e4e ("Input: extend the number of event (and other) devices") made evdev, joydev and mousedev to embed struct cdev into their respective structures representing input devices. Unfortunately character device structure may outlive the parent structure unless we do not set it up as parent of character device so that it will stay pinned until character device is freed. Also, now that parent structure is pinned while character device exists we do not need to pin and unpin it every time user opens or closes it. Reported-by: Dave Jones <davej@redhat.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/evdev.c3
-rw-r--r--drivers/input/joydev.c3
-rw-r--r--drivers/input/mousedev.c3
3 files changed, 3 insertions, 6 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 6ae2ac47c9c8..f0f8928b3c8a 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file)
292 kfree(client); 292 kfree(client);
293 293
294 evdev_close_device(evdev); 294 evdev_close_device(evdev);
295 put_device(&evdev->dev);
296 295
297 return 0; 296 return 0;
298} 297}
@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
331 file->private_data = client; 330 file->private_data = client;
332 nonseekable_open(inode, file); 331 nonseekable_open(inode, file);
333 332
334 get_device(&evdev->dev);
335 return 0; 333 return 0;
336 334
337 err_free_client: 335 err_free_client:
@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
1001 goto err_free_evdev; 999 goto err_free_evdev;
1002 1000
1003 cdev_init(&evdev->cdev, &evdev_fops); 1001 cdev_init(&evdev->cdev, &evdev_fops);
1002 evdev->cdev.kobj.parent = &evdev->dev.kobj;
1004 error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); 1003 error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
1005 if (error) 1004 if (error)
1006 goto err_unregister_handle; 1005 goto err_unregister_handle;
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index b62b5891f399..f362883c94e3 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file)
243 kfree(client); 243 kfree(client);
244 244
245 joydev_close_device(joydev); 245 joydev_close_device(joydev);
246 put_device(&joydev->dev);
247 246
248 return 0; 247 return 0;
249} 248}
@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
270 file->private_data = client; 269 file->private_data = client;
271 nonseekable_open(inode, file); 270 nonseekable_open(inode, file);
272 271
273 get_device(&joydev->dev);
274 return 0; 272 return 0;
275 273
276 err_free_client: 274 err_free_client:
@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
858 goto err_free_joydev; 856 goto err_free_joydev;
859 857
860 cdev_init(&joydev->cdev, &joydev_fops); 858 cdev_init(&joydev->cdev, &joydev_fops);
859 joydev->cdev.kobj.parent = &joydev->dev.kobj;
861 error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); 860 error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
862 if (error) 861 if (error)
863 goto err_unregister_handle; 862 goto err_unregister_handle;
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index a1b4c37956b2..8f02e3d0e712 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file)
523 kfree(client); 523 kfree(client);
524 524
525 mousedev_close_device(mousedev); 525 mousedev_close_device(mousedev);
526 put_device(&mousedev->dev);
527 526
528 return 0; 527 return 0;
529} 528}
@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
558 file->private_data = client; 557 file->private_data = client;
559 nonseekable_open(inode, file); 558 nonseekable_open(inode, file);
560 559
561 get_device(&mousedev->dev);
562 return 0; 560 return 0;
563 561
564 err_free_client: 562 err_free_client:
@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
892 } 890 }
893 891
894 cdev_init(&mousedev->cdev, &mousedev_fops); 892 cdev_init(&mousedev->cdev, &mousedev_fops);
893 mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
895 error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); 894 error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
896 if (error) 895 if (error)
897 goto err_unregister_handle; 896 goto err_unregister_handle;