Skip to content

Commit

Permalink
tty: Convert termios_mutex to termios_rwsem
Browse files Browse the repository at this point in the history
termios is commonly accessed unsafely (especially by N_TTY)
because the existing mutex forces exclusive access.
Convert existing usage.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
peterhurley authored and gregkh committed Jul 23, 2013
1 parent a2f73be commit 6a1c068
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 69 deletions.
8 changes: 4 additions & 4 deletions drivers/net/irda/irtty-sir.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)

tty = priv->tty;

mutex_lock(&tty->termios_mutex);
down_write(&tty->termios_rwsem);
old_termios = tty->termios;
cflag = tty->termios.c_cflag;
tty_encode_baud_rate(tty, speed, speed);
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
priv->io.speed = speed;
mutex_unlock(&tty->termios_mutex);
up_write(&tty->termios_rwsem);

return 0;
}
Expand Down Expand Up @@ -280,7 +280,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
struct ktermios old_termios;
int cflag;

mutex_lock(&tty->termios_mutex);
down_write(&tty->termios_rwsem);
old_termios = tty->termios;
cflag = tty->termios.c_cflag;

Expand All @@ -292,7 +292,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
tty->termios.c_cflag = cflag;
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
mutex_unlock(&tty->termios_mutex);
up_write(&tty->termios_rwsem);
}

/*****************************************************************/
Expand Down
2 changes: 1 addition & 1 deletion drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -1539,7 +1539,7 @@ int is_ignored(int sig)
* guaranteed that this function will not be re-entered or in progress
* when the ldisc is closed.
*
* Locking: Caller holds tty->termios_mutex
* Locking: Caller holds tty->termios_rwsem
*/

static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
Expand Down
4 changes: 2 additions & 2 deletions drivers/tty/pty.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws)
struct tty_struct *pty = tty->link;

/* For a PTY we need to lock the tty side */
mutex_lock(&tty->termios_mutex);
down_write(&tty->termios_rwsem);
if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;

Expand All @@ -314,7 +314,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws)
tty->winsize = *ws;
pty->winsize = *ws; /* Never used so will go away soon */
done:
mutex_unlock(&tty->termios_mutex);
up_write(&tty->termios_rwsem);
return 0;
}

Expand Down
14 changes: 7 additions & 7 deletions drivers/tty/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ static int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
* redirect lock for undoing redirection
* file list lock for manipulating list of ttys
* tty_ldiscs_lock from called functions
* termios_mutex resetting termios data
* termios_rwsem resetting termios data
* tasklist_lock to walk task list for hangup event
* ->siglock to protect ->signal/->sighand
*/
Expand Down Expand Up @@ -2230,17 +2230,17 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
*
* Copies the kernel idea of the window size into the user buffer.
*
* Locking: tty->termios_mutex is taken to ensure the winsize data
* Locking: tty->termios_rwsem is taken to ensure the winsize data
* is consistent.
*/

static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
{
int err;

mutex_lock(&tty->termios_mutex);
down_read(&tty->termios_rwsem);
err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
mutex_unlock(&tty->termios_mutex);
up_read(&tty->termios_rwsem);

return err ? -EFAULT: 0;
}
Expand All @@ -2261,7 +2261,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
unsigned long flags;

/* Lock the tty */
mutex_lock(&tty->termios_mutex);
down_write(&tty->termios_rwsem);
if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;
/* Get the PID values and reference them so we can
Expand All @@ -2276,7 +2276,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws)

tty->winsize = *ws;
done:
mutex_unlock(&tty->termios_mutex);
up_write(&tty->termios_rwsem);
return 0;
}
EXPORT_SYMBOL(tty_do_resize);
Expand Down Expand Up @@ -3015,7 +3015,7 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->session = NULL;
tty->pgrp = NULL;
mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
init_rwsem(&tty->termios_rwsem);
init_ldsem(&tty->ldisc_sem);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
Expand Down
Loading

0 comments on commit 6a1c068

Please sign in to comment.