aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/pty.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2012-07-27 13:02:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-27 14:55:59 -0400
commitd155255a344c417acad74156654295a2964e6b81 (patch)
tree71f7c39fda7d71980a64a5e1e35c08cf5c948820 /drivers/tty/pty.c
parent373f5aedbc6fb73d30f00eeb0dc7313ecfede908 (diff)
tty: Fix race in tty release
Ian Abbott found that the tty layer would explode with the right set of parallel open and close operations. This is because we race in the handling of tty->drivers->termios[]. Correct this by Making tty_ldisc_release behave like nromal code (takes the lock, does stuff, drops the lock) Drop the tty lock earlier in tty_ldisc_release Taking the tty mutex around the driver->termios update in all cases Adding a WARN_ON to catch future screwups. I also forgot to clean up the pty resources properly. With a pty pair we need to pull both halves out of the tables. Signed-off-by: Alan Cox <alan@linux.intel.com> Tested-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/pty.c')
-rw-r--r--drivers/tty/pty.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 60c08ce83782..d6579a9064c4 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -282,6 +282,17 @@ done:
282 return 0; 282 return 0;
283} 283}
284 284
285/**
286 * pty_common_install - set up the pty pair
287 * @driver: the pty driver
288 * @tty: the tty being instantiated
289 * @bool: legacy, true if this is BSD style
290 *
291 * Perform the initial set up for the tty/pty pair. Called from the
292 * tty layer when the port is first opened.
293 *
294 * Locking: the caller must hold the tty_mutex
295 */
285static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, 296static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
286 bool legacy) 297 bool legacy)
287{ 298{
@@ -364,6 +375,14 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
364 return pty_common_install(driver, tty, true); 375 return pty_common_install(driver, tty, true);
365} 376}
366 377
378static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
379{
380 struct tty_struct *pair = tty->link;
381 driver->ttys[tty->index] = NULL;
382 if (pair)
383 pair->driver->ttys[pair->index] = NULL;
384}
385
367static int pty_bsd_ioctl(struct tty_struct *tty, 386static int pty_bsd_ioctl(struct tty_struct *tty,
368 unsigned int cmd, unsigned long arg) 387 unsigned int cmd, unsigned long arg)
369{ 388{
@@ -395,7 +414,8 @@ static const struct tty_operations master_pty_ops_bsd = {
395 .set_termios = pty_set_termios, 414 .set_termios = pty_set_termios,
396 .ioctl = pty_bsd_ioctl, 415 .ioctl = pty_bsd_ioctl,
397 .cleanup = pty_cleanup, 416 .cleanup = pty_cleanup,
398 .resize = pty_resize 417 .resize = pty_resize,
418 .remove = pty_remove
399}; 419};
400 420
401static const struct tty_operations slave_pty_ops_bsd = { 421static const struct tty_operations slave_pty_ops_bsd = {
@@ -409,7 +429,8 @@ static const struct tty_operations slave_pty_ops_bsd = {
409 .unthrottle = pty_unthrottle, 429 .unthrottle = pty_unthrottle,
410 .set_termios = pty_set_termios, 430 .set_termios = pty_set_termios,
411 .cleanup = pty_cleanup, 431 .cleanup = pty_cleanup,
412 .resize = pty_resize 432 .resize = pty_resize,
433 .remove = pty_remove
413}; 434};
414 435
415static void __init legacy_pty_init(void) 436static void __init legacy_pty_init(void)