From c1a752ba2d6b8a52879c7ab637cff38359ea9827 Mon Sep 17 00:00:00 2001 From: Leon Yu Date: Mon, 7 Sep 2015 13:08:37 +0000 Subject: 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 Fixes: a3a10ce3429e ("Avoid usb reset crashes by making tty_io cdevs truly dynamic") Acked-by: Richard Watts Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/tty') 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; static int tty_cdev_add(struct tty_driver *driver, dev_t dev, unsigned int index, unsigned int count) { + int err; + /* init here, since reused cdevs cause crashes */ driver->cdevs[index] = cdev_alloc(); if (!driver->cdevs[index]) return -ENOMEM; - cdev_init(driver->cdevs[index], &tty_fops); + driver->cdevs[index]->ops = &tty_fops; driver->cdevs[index]->owner = driver->owner; - return cdev_add(driver->cdevs[index], dev, count); + err = cdev_add(driver->cdevs[index], dev, count); + if (err) + kobject_put(&driver->cdevs[index]->kobj); + return err; } /** -- cgit v1.2.3