aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeon Yu <chianglungyu@gmail.com>2015-09-07 09:08:37 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-10-04 13:51:42 -0400
commitc1a752ba2d6b8a52879c7ab637cff38359ea9827 (patch)
tree97a4090ddc27d70b3ca2c4b50941748395621a0e
parent0c727a42043f79db210cdde0366f9137b9c6bf5a (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.c9
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;
3151static int tty_cdev_add(struct tty_driver *driver, dev_t dev, 3151static 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/**