Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756432AbbESPmf (ORCPT ); Tue, 19 May 2015 11:42:35 -0400 Received: from rrw.me.uk ([93.93.129.10]:49413 "EHLO rrw.me.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757220AbbESPmP (ORCPT ); Tue, 19 May 2015 11:42:15 -0400 Message-ID: <555B518D.2010102@kynesim.co.uk> Date: Tue, 19 May 2015 16:06:53 +0100 From: Richard Watts User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: linux-kernel@vger.kernel.org, gregkh@linuxfoundation.org Subject: [PATCH 1/1] Avoid usb reset crashes by making tty_io cdevs truly dynamic Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2985 Lines: 95 Avoid usb reset crashes by making tty_io cdevs truly dynamic Signed-off-by: Richard Watts Reported-by: Duncan Mackintosh --- drivers/tty/tty_io.c | 24 ++++++++++++++++-------- include/linux/tty_driver.h | 2 +- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index e569546..699cf20 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3168,9 +3168,12 @@ static int tty_cdev_add(struct tty_driver *driver, dev_t dev, unsigned int index, unsigned int count) { /* init here, since reused cdevs cause crashes */ - cdev_init(&driver->cdevs[index], &tty_fops); - driver->cdevs[index].owner = driver->owner; - return cdev_add(&driver->cdevs[index], dev, count); + driver->cdevs[index] = cdev_alloc(); + if (!driver->cdevs[index]) + return -ENOMEM; + cdev_init(driver->cdevs[index], &tty_fops); + driver->cdevs[index]->owner = driver->owner; + return cdev_add(driver->cdevs[index], dev, count); } /** @@ -3276,8 +3279,10 @@ struct device *tty_register_device_attr(struct tty_driver *driver, error: put_device(dev); - if (cdev) - cdev_del(&driver->cdevs[index]); + if (cdev) { + cdev_del(driver->cdevs[index]); + driver->cdevs[index] = NULL; + } return ERR_PTR(retval); } EXPORT_SYMBOL_GPL(tty_register_device_attr); @@ -3297,8 +3302,10 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index) { device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); - if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) - cdev_del(&driver->cdevs[index]); + if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) { + cdev_del(driver->cdevs[index]); + driver->cdevs[index] = NULL; + } } EXPORT_SYMBOL(tty_unregister_device); @@ -3363,6 +3370,7 @@ err_free_all: kfree(driver->ports); kfree(driver->ttys); kfree(driver->termios); + kfree(driver->cdevs); kfree(driver); return ERR_PTR(err); } @@ -3391,7 +3399,7 @@ static void destruct_tty_driver(struct kref *kref) } proc_tty_unregister_driver(driver); if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC) - cdev_del(&driver->cdevs[0]); + cdev_del(driver->cdevs[0]); } kfree(driver->cdevs); kfree(driver->ports); diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 92e337c..1610524 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h @@ -296,7 +296,7 @@ struct tty_operations { struct tty_driver { int magic; /* magic number for this structure */ struct kref kref; /* Reference management */ - struct cdev *cdevs; + struct cdev **cdevs; struct module *owner; const char *driver_name; const char *name; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/