summaryrefslogtreecommitdiffstats
path: root/drivers/tty/pty.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2012-07-27 18:02:54 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-27 11:55:59 -0700
commitd155255a344c417acad74156654295a2964e6b81 (patch)
tree71f7c39fda7d71980a64a5e1e35c08cf5c948820 /drivers/tty/pty.c
parent373f5aedbc6fb73d30f00eeb0dc7313ecfede908 (diff)
downloadop-kernel-dev-d155255a344c417acad74156654295a2964e6b81.zip
op-kernel-dev-d155255a344c417acad74156654295a2964e6b81.tar.gz
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 60c08ce..d6579a9 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -282,6 +282,17 @@ done:
return 0;
}
+/**
+ * pty_common_install - set up the pty pair
+ * @driver: the pty driver
+ * @tty: the tty being instantiated
+ * @bool: legacy, true if this is BSD style
+ *
+ * Perform the initial set up for the tty/pty pair. Called from the
+ * tty layer when the port is first opened.
+ *
+ * Locking: the caller must hold the tty_mutex
+ */
static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
bool legacy)
{
@@ -364,6 +375,14 @@ static int pty_install(struct tty_driver *driver, struct tty_struct *tty)
return pty_common_install(driver, tty, true);
}
+static void pty_remove(struct tty_driver *driver, struct tty_struct *tty)
+{
+ struct tty_struct *pair = tty->link;
+ driver->ttys[tty->index] = NULL;
+ if (pair)
+ pair->driver->ttys[pair->index] = NULL;
+}
+
static int pty_bsd_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
@@ -395,7 +414,8 @@ static const struct tty_operations master_pty_ops_bsd = {
.set_termios = pty_set_termios,
.ioctl = pty_bsd_ioctl,
.cleanup = pty_cleanup,
- .resize = pty_resize
+ .resize = pty_resize,
+ .remove = pty_remove
};
static const struct tty_operations slave_pty_ops_bsd = {
@@ -409,7 +429,8 @@ static const struct tty_operations slave_pty_ops_bsd = {
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
.cleanup = pty_cleanup,
- .resize = pty_resize
+ .resize = pty_resize,
+ .remove = pty_remove
};
static void __init legacy_pty_init(void)
OpenPOWER on IntegriCloud