diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 00:53:59 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 08:29:45 -0700 |
commit | 978e595f88a1fba5869aa42a4af4fba36f33ecac (patch) | |
tree | 60848f49949c5b7b518621ee36cdc6d500244539 /drivers/char/tty_ioctl.c | |
parent | ac0e4b7d319bf284bb64bc7e1c051417386b34a4 (diff) | |
download | lwn-978e595f88a1fba5869aa42a4af4fba36f33ecac.tar.gz lwn-978e595f88a1fba5869aa42a4af4fba36f33ecac.zip |
tty/serial: lay the foundations for the next set of reworks
- Stop drivers calling their own flush method indirectly, it obfuscates code
and it will change soon anyway
- A few more lock_kernel paths temporarily needed in some driver internal
waiting code
- Remove private put_char method that does a write call for one char - we
have that anyway
- Most but not yet all of the termios copy under lock fixing (some has other
dependencies to follow)
- Note a few locking bugs in drivers found in the process
- Kill remaining [ab]users of TIOCG/SSOFTCAR in the driver, these must go to
fix the termios locking
Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_ioctl.c')
-rw-r--r-- | drivers/char/tty_ioctl.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index d769e43f73fb..8c4bf3e48d5b 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -396,7 +396,7 @@ EXPORT_SYMBOL(tty_termios_hw_change); static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) { int canon_change; - struct ktermios old_termios = *tty->termios; + struct ktermios old_termios; struct tty_ldisc *ld; unsigned long flags; @@ -408,7 +408,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) /* FIXME: we need to decide on some locking/ordering semantics for the set_termios notification eventually */ mutex_lock(&tty->termios_mutex); - + old_termios = *tty->termios; *tty->termios = *new_termios; unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; @@ -480,7 +480,9 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) if (retval) return retval; + mutex_lock(&tty->termios_mutex); memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios)); + mutex_unlock(&tty->termios_mutex); if (opt & TERMIOS_TERMIO) { if (user_termio_to_kernel_termios(&tmp_termios, @@ -666,12 +668,14 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars) { struct tchars tmp; + mutex_lock(&tty->termios_mutex); tmp.t_intrc = tty->termios->c_cc[VINTR]; tmp.t_quitc = tty->termios->c_cc[VQUIT]; tmp.t_startc = tty->termios->c_cc[VSTART]; tmp.t_stopc = tty->termios->c_cc[VSTOP]; tmp.t_eofc = tty->termios->c_cc[VEOF]; tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */ + mutex_unlock(&tty->termios_mutex); return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -681,12 +685,14 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars) if (copy_from_user(&tmp, tchars, sizeof(tmp))) return -EFAULT; + mutex_lock(&tty->termios_mutex); tty->termios->c_cc[VINTR] = tmp.t_intrc; tty->termios->c_cc[VQUIT] = tmp.t_quitc; tty->termios->c_cc[VSTART] = tmp.t_startc; tty->termios->c_cc[VSTOP] = tmp.t_stopc; tty->termios->c_cc[VEOF] = tmp.t_eofc; tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ + mutex_unlock(&tty->termios_mutex); return 0; } #endif @@ -696,6 +702,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) { struct ltchars tmp; + mutex_lock(&tty->termios_mutex); tmp.t_suspc = tty->termios->c_cc[VSUSP]; /* what is dsuspc anyway? */ tmp.t_dsuspc = tty->termios->c_cc[VSUSP]; @@ -704,6 +711,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) tmp.t_flushc = tty->termios->c_cc[VEOL2]; tmp.t_werasc = tty->termios->c_cc[VWERASE]; tmp.t_lnextc = tty->termios->c_cc[VLNEXT]; + mutex_unlock(&tty->termios_mutex); return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -714,6 +722,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) if (copy_from_user(&tmp, ltchars, sizeof(tmp))) return -EFAULT; + mutex_lock(&tty->termios_mutex); tty->termios->c_cc[VSUSP] = tmp.t_suspc; /* what is dsuspc anyway? */ tty->termios->c_cc[VEOL2] = tmp.t_dsuspc; @@ -722,6 +731,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) tty->termios->c_cc[VEOL2] = tmp.t_flushc; tty->termios->c_cc[VWERASE] = tmp.t_werasc; tty->termios->c_cc[VLNEXT] = tmp.t_lnextc; + mutex_unlock(&tty->termios_mutex); return 0; } #endif |