diff options
author | Johan Hovold <johan@kernel.org> | 2015-01-05 10:04:13 -0500 |
---|---|---|
committer | Johan Hovold <johan@kernel.org> | 2015-01-10 06:48:21 -0500 |
commit | 32a4bf2e81ec378e5925d4e069e0677a6c86a6ad (patch) | |
tree | 7060d862f8df27bd46007e6d30ac38ca2e8eafa2 /drivers/usb/serial | |
parent | d269d4434c72ed0da3a9b1230c30da82c4918c63 (diff) |
USB: console: fix potential use after free
Use tty kref to release the fake tty in usb_console_setup to avoid use
after free if the underlying serial driver has acquired a reference.
Note that using the tty destructor release_one_tty requires some more
state to be initialised.
Fixes: 4a90f09b20f4 ("tty: usb-serial krefs")
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/console.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index e56f394b58d8..29fa1c3d0089 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -46,6 +46,8 @@ static struct console usbcons; | |||
46 | * ------------------------------------------------------------ | 46 | * ------------------------------------------------------------ |
47 | */ | 47 | */ |
48 | 48 | ||
49 | static const struct tty_operations usb_console_fake_tty_ops = { | ||
50 | }; | ||
49 | 51 | ||
50 | /* | 52 | /* |
51 | * The parsing of the command line works exactly like the | 53 | * The parsing of the command line works exactly like the |
@@ -137,14 +139,17 @@ static int usb_console_setup(struct console *co, char *options) | |||
137 | goto reset_open_count; | 139 | goto reset_open_count; |
138 | } | 140 | } |
139 | kref_init(&tty->kref); | 141 | kref_init(&tty->kref); |
140 | tty_port_tty_set(&port->port, tty); | ||
141 | tty->driver = usb_serial_tty_driver; | 142 | tty->driver = usb_serial_tty_driver; |
142 | tty->index = co->index; | 143 | tty->index = co->index; |
143 | init_ldsem(&tty->ldisc_sem); | 144 | init_ldsem(&tty->ldisc_sem); |
145 | INIT_LIST_HEAD(&tty->tty_files); | ||
146 | kref_get(&tty->driver->kref); | ||
147 | tty->ops = &usb_console_fake_tty_ops; | ||
144 | if (tty_init_termios(tty)) { | 148 | if (tty_init_termios(tty)) { |
145 | retval = -ENOMEM; | 149 | retval = -ENOMEM; |
146 | goto free_tty; | 150 | goto put_tty; |
147 | } | 151 | } |
152 | tty_port_tty_set(&port->port, tty); | ||
148 | } | 153 | } |
149 | 154 | ||
150 | /* only call the device specific open if this | 155 | /* only call the device specific open if this |
@@ -162,7 +167,7 @@ static int usb_console_setup(struct console *co, char *options) | |||
162 | serial->type->set_termios(tty, port, &dummy); | 167 | serial->type->set_termios(tty, port, &dummy); |
163 | 168 | ||
164 | tty_port_tty_set(&port->port, NULL); | 169 | tty_port_tty_set(&port->port, NULL); |
165 | kfree(tty); | 170 | tty_kref_put(tty); |
166 | } | 171 | } |
167 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); | 172 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); |
168 | } | 173 | } |
@@ -178,8 +183,8 @@ static int usb_console_setup(struct console *co, char *options) | |||
178 | 183 | ||
179 | fail: | 184 | fail: |
180 | tty_port_tty_set(&port->port, NULL); | 185 | tty_port_tty_set(&port->port, NULL); |
181 | free_tty: | 186 | put_tty: |
182 | kfree(tty); | 187 | tty_kref_put(tty); |
183 | reset_open_count: | 188 | reset_open_count: |
184 | port->port.count = 0; | 189 | port->port.count = 0; |
185 | usb_autopm_put_interface(serial->interface); | 190 | usb_autopm_put_interface(serial->interface); |