diff options
author | Leon Yu <chianglungyu@gmail.com> | 2015-09-07 09:08:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-04 13:51:42 -0400 |
commit | c1a752ba2d6b8a52879c7ab637cff38359ea9827 (patch) | |
tree | 97a4090ddc27d70b3ca2c4b50941748395621a0e | |
parent | 0c727a42043f79db210cdde0366f9137b9c6bf5a (diff) |
tty: don't leak cdev in tty_cdev_add()
Commit a3a10ce3429e ("Avoid usb reset crashes by making tty_io cdevs truly
dynamic") which mixes using cdev_alloc() and cdev_init() is problematic.
Subsequent call to cdev_init() after cdev_alloc() sets kobj release method
from cdev_dynamic_release() to cdev_default_release() and thus makes it
impossible to free allocated cdev.
This patch also consolidates error path of cdev_add() as cdev can also leak
here if things went wrong.
Signed-off-by: Leon Yu <chianglungyu@gmail.com>
Fixes: a3a10ce3429e ("Avoid usb reset crashes by making tty_io cdevs truly dynamic")
Acked-by: Richard Watts <rrw@kynesim.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/tty_io.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 02785d844354..17b027242734 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -3151,13 +3151,18 @@ struct class *tty_class; | |||
3151 | static int tty_cdev_add(struct tty_driver *driver, dev_t dev, | 3151 | static int tty_cdev_add(struct tty_driver *driver, dev_t dev, |
3152 | unsigned int index, unsigned int count) | 3152 | unsigned int index, unsigned int count) |
3153 | { | 3153 | { |
3154 | int err; | ||
3155 | |||
3154 | /* init here, since reused cdevs cause crashes */ | 3156 | /* init here, since reused cdevs cause crashes */ |
3155 | driver->cdevs[index] = cdev_alloc(); | 3157 | driver->cdevs[index] = cdev_alloc(); |
3156 | if (!driver->cdevs[index]) | 3158 | if (!driver->cdevs[index]) |
3157 | return -ENOMEM; | 3159 | return -ENOMEM; |
3158 | cdev_init(driver->cdevs[index], &tty_fops); | 3160 | driver->cdevs[index]->ops = &tty_fops; |
3159 | driver->cdevs[index]->owner = driver->owner; | 3161 | driver->cdevs[index]->owner = driver->owner; |
3160 | return cdev_add(driver->cdevs[index], dev, count); | 3162 | err = cdev_add(driver->cdevs[index], dev, count); |
3163 | if (err) | ||
3164 | kobject_put(&driver->cdevs[index]->kobj); | ||
3165 | return err; | ||
3161 | } | 3166 | } |
3162 | 3167 | ||
3163 | /** | 3168 | /** |