Skip to content

Commit

Permalink
Input: fix use-after-free introduced with dynamic minor changes
Browse files Browse the repository at this point in the history
Commit 7f8d4ca ("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 <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
Acked-by: Al Viro <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
dtor authored and torvalds committed Oct 22, 2012
1 parent 2f0157f commit 4a215aa
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 6 deletions.
3 changes: 1 addition & 2 deletions drivers/input/evdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions drivers/input/joydev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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:
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions drivers/input/mousedev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 4a215aa

Please sign in to comment.