diff options
author | Arnd Bergmann <arnd@arndb.de> | 2010-06-01 22:53:02 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-10 13:47:43 -0700 |
commit | 64ba3dc3143d94bbe935722aa17fa516b232bc83 (patch) | |
tree | 9649ffd431eb8dc97fbad83d47feaed96980cb7e /drivers/char/pty.c | |
parent | ec79d6056de58511d8e46d9ae59d3878f958dc3e (diff) | |
download | blackbird-obmc-linux-64ba3dc3143d94bbe935722aa17fa516b232bc83.tar.gz blackbird-obmc-linux-64ba3dc3143d94bbe935722aa17fa516b232bc83.zip |
tty: never hold BTM while getting tty_mutex
tty_mutex is never taken with the BTM held, except for
two corner cases that are worked around here.
We give up the BTM before calling tty_release() in the
error path of tty_open().
Similarly, we reorder the locking in ptmx_open()
to get tty_mutex before the BTM.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/char/pty.c')
-rw-r--r-- | drivers/char/pty.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 622e21ca9a5c..de22ea952832 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -647,7 +647,7 @@ static const struct tty_operations pty_unix98_ops = { * allocated_ptys_lock handles the list of free pty numbers */ -static int __ptmx_open(struct inode *inode, struct file *filp) +static int ptmx_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int retval; @@ -656,11 +656,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp) nonseekable_open(inode, filp); /* find a device that is not in use. */ + tty_lock(); index = devpts_new_index(inode); + tty_unlock(); if (index < 0) return index; mutex_lock(&tty_mutex); + tty_lock(); tty = tty_init_dev(ptm_driver, index, 1); mutex_unlock(&tty_mutex); @@ -678,24 +681,19 @@ static int __ptmx_open(struct inode *inode, struct file *filp) goto out1; retval = ptm_driver->ops->open(tty, filp); - if (!retval) - return 0; + if (retval) + goto out2; out1: + tty_unlock(); + return retval; +out2: + tty_unlock(); tty_release(inode, filp); return retval; out: devpts_kill_index(inode, index); - return retval; -} - -static int ptmx_open(struct inode *inode, struct file *filp) -{ - int ret; - - tty_lock(); - ret = __ptmx_open(inode, filp); tty_unlock(); - return ret; + return retval; } static struct file_operations ptmx_fops; |