Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Dmitry Torokhov and committed by
Linus Torvalds
4a215aad 2f0157f1

+3 -6
+1 -2
drivers/input/evdev.c
··· 292 292 kfree(client); 293 293 294 294 evdev_close_device(evdev); 295 - put_device(&evdev->dev); 296 295 297 296 return 0; 298 297 } ··· 330 331 file->private_data = client; 331 332 nonseekable_open(inode, file); 332 333 333 - get_device(&evdev->dev); 334 334 return 0; 335 335 336 336 err_free_client: ··· 999 1001 goto err_free_evdev; 1000 1002 1001 1003 cdev_init(&evdev->cdev, &evdev_fops); 1004 + evdev->cdev.kobj.parent = &evdev->dev.kobj; 1002 1005 error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); 1003 1006 if (error) 1004 1007 goto err_unregister_handle;
+1 -2
drivers/input/joydev.c
··· 243 243 kfree(client); 244 244 245 245 joydev_close_device(joydev); 246 - put_device(&joydev->dev); 247 246 248 247 return 0; 249 248 } ··· 269 270 file->private_data = client; 270 271 nonseekable_open(inode, file); 271 272 272 - get_device(&joydev->dev); 273 273 return 0; 274 274 275 275 err_free_client: ··· 856 858 goto err_free_joydev; 857 859 858 860 cdev_init(&joydev->cdev, &joydev_fops); 861 + joydev->cdev.kobj.parent = &joydev->dev.kobj; 859 862 error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); 860 863 if (error) 861 864 goto err_unregister_handle;
+1 -2
drivers/input/mousedev.c
··· 523 523 kfree(client); 524 524 525 525 mousedev_close_device(mousedev); 526 - put_device(&mousedev->dev); 527 526 528 527 return 0; 529 528 } ··· 557 558 file->private_data = client; 558 559 nonseekable_open(inode, file); 559 560 560 - get_device(&mousedev->dev); 561 561 return 0; 562 562 563 563 err_free_client: ··· 890 892 } 891 893 892 894 cdev_init(&mousedev->cdev, &mousedev_fops); 895 + mousedev->cdev.kobj.parent = &mousedev->dev.kobj; 893 896 error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); 894 897 if (error) 895 898 goto err_unregister_handle;