Commit 4a215aad authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Linus Torvalds

Input: fix use-after-free introduced with dynamic minor changes

Commit 7f8d4cad ("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: default avatarDave Jones <davej@redhat.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2f0157f1
...@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file) ...@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file)
kfree(client); kfree(client);
evdev_close_device(evdev); evdev_close_device(evdev);
put_device(&evdev->dev);
return 0; return 0;
} }
...@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file) ...@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
file->private_data = client; file->private_data = client;
nonseekable_open(inode, file); nonseekable_open(inode, file);
get_device(&evdev->dev);
return 0; return 0;
err_free_client: err_free_client:
...@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
goto err_free_evdev; goto err_free_evdev;
cdev_init(&evdev->cdev, &evdev_fops); cdev_init(&evdev->cdev, &evdev_fops);
evdev->cdev.kobj.parent = &evdev->dev.kobj;
error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
if (error) if (error)
goto err_unregister_handle; goto err_unregister_handle;
......
...@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file) ...@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file)
kfree(client); kfree(client);
joydev_close_device(joydev); joydev_close_device(joydev);
put_device(&joydev->dev);
return 0; return 0;
} }
...@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file) ...@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
file->private_data = client; file->private_data = client;
nonseekable_open(inode, file); nonseekable_open(inode, file);
get_device(&joydev->dev);
return 0; return 0;
err_free_client: err_free_client:
...@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
goto err_free_joydev; goto err_free_joydev;
cdev_init(&joydev->cdev, &joydev_fops); cdev_init(&joydev->cdev, &joydev_fops);
joydev->cdev.kobj.parent = &joydev->dev.kobj;
error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
if (error) if (error)
goto err_unregister_handle; goto err_unregister_handle;
......
...@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file) ...@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file)
kfree(client); kfree(client);
mousedev_close_device(mousedev); mousedev_close_device(mousedev);
put_device(&mousedev->dev);
return 0; return 0;
} }
...@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file) ...@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
file->private_data = client; file->private_data = client;
nonseekable_open(inode, file); nonseekable_open(inode, file);
get_device(&mousedev->dev);
return 0; return 0;
err_free_client: err_free_client:
...@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev, ...@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
} }
cdev_init(&mousedev->cdev, &mousedev_fops); cdev_init(&mousedev->cdev, &mousedev_fops);
mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
if (error) if (error)
goto err_unregister_handle; goto err_unregister_handle;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment