summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-10-21 17:57:20 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-22 08:50:37 +0300
commit4a215aade0baa0487d4644d7aef6f166c84c516e (patch)
tree3cf126e431235d21fdf565e2d39089397680e803
parent2f0157f13f42800aa3d9017ebb0fb80a65f7b2de (diff)
downloadlinux-stable-4a215aade0baa0487d4644d7aef6f166c84c516e.tar.gz
linux-stable-4a215aade0baa0487d4644d7aef6f166c84c516e.tar.bz2
linux-stable-4a215aade0baa0487d4644d7aef6f166c84c516e.zip
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>
-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)
kfree(client);
evdev_close_device(evdev);
- put_device(&evdev->dev);
return 0;
}
@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
file->private_data = client;
nonseekable_open(inode, file);
- get_device(&evdev->dev);
return 0;
err_free_client:
@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
goto err_free_evdev;
cdev_init(&evdev->cdev, &evdev_fops);
+ evdev->cdev.kobj.parent = &evdev->dev.kobj;
error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
if (error)
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)
kfree(client);
joydev_close_device(joydev);
- put_device(&joydev->dev);
return 0;
}
@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
file->private_data = client;
nonseekable_open(inode, file);
- get_device(&joydev->dev);
return 0;
err_free_client:
@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
goto err_free_joydev;
cdev_init(&joydev->cdev, &joydev_fops);
+ joydev->cdev.kobj.parent = &joydev->dev.kobj;
error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
if (error)
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)
kfree(client);
mousedev_close_device(mousedev);
- put_device(&mousedev->dev);
return 0;
}
@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
file->private_data = client;
nonseekable_open(inode, file);
- get_device(&mousedev->dev);
return 0;
err_free_client:
@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
}
cdev_init(&mousedev->cdev, &mousedev_fops);
+ mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
if (error)
goto err_unregister_handle;