|
@@ -396,7 +396,7 @@ EXPORT_SYMBOL(tty_termios_hw_change);
|
|
static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
|
static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
|
|
{
|
|
{
|
|
int canon_change;
|
|
int canon_change;
|
|
- struct ktermios old_termios = *tty->termios;
|
|
|
|
|
|
+ struct ktermios old_termios;
|
|
struct tty_ldisc *ld;
|
|
struct tty_ldisc *ld;
|
|
unsigned long flags;
|
|
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
|
|
/* FIXME: we need to decide on some locking/ordering semantics
|
|
for the set_termios notification eventually */
|
|
for the set_termios notification eventually */
|
|
mutex_lock(&tty->termios_mutex);
|
|
mutex_lock(&tty->termios_mutex);
|
|
-
|
|
|
|
|
|
+ old_termios = *tty->termios;
|
|
*tty->termios = *new_termios;
|
|
*tty->termios = *new_termios;
|
|
unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
|
|
unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
|
|
canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
|
|
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)
|
|
if (retval)
|
|
return retval;
|
|
return retval;
|
|
|
|
|
|
|
|
+ mutex_lock(&tty->termios_mutex);
|
|
memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
|
|
memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
|
|
|
|
+ mutex_unlock(&tty->termios_mutex);
|
|
|
|
|
|
if (opt & TERMIOS_TERMIO) {
|
|
if (opt & TERMIOS_TERMIO) {
|
|
if (user_termio_to_kernel_termios(&tmp_termios,
|
|
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;
|
|
struct tchars tmp;
|
|
|
|
|
|
|
|
+ mutex_lock(&tty->termios_mutex);
|
|
tmp.t_intrc = tty->termios->c_cc[VINTR];
|
|
tmp.t_intrc = tty->termios->c_cc[VINTR];
|
|
tmp.t_quitc = tty->termios->c_cc[VQUIT];
|
|
tmp.t_quitc = tty->termios->c_cc[VQUIT];
|
|
tmp.t_startc = tty->termios->c_cc[VSTART];
|
|
tmp.t_startc = tty->termios->c_cc[VSTART];
|
|
tmp.t_stopc = tty->termios->c_cc[VSTOP];
|
|
tmp.t_stopc = tty->termios->c_cc[VSTOP];
|
|
tmp.t_eofc = tty->termios->c_cc[VEOF];
|
|
tmp.t_eofc = tty->termios->c_cc[VEOF];
|
|
tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
|
|
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;
|
|
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)))
|
|
if (copy_from_user(&tmp, tchars, sizeof(tmp)))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
|
|
+ mutex_lock(&tty->termios_mutex);
|
|
tty->termios->c_cc[VINTR] = tmp.t_intrc;
|
|
tty->termios->c_cc[VINTR] = tmp.t_intrc;
|
|
tty->termios->c_cc[VQUIT] = tmp.t_quitc;
|
|
tty->termios->c_cc[VQUIT] = tmp.t_quitc;
|
|
tty->termios->c_cc[VSTART] = tmp.t_startc;
|
|
tty->termios->c_cc[VSTART] = tmp.t_startc;
|
|
tty->termios->c_cc[VSTOP] = tmp.t_stopc;
|
|
tty->termios->c_cc[VSTOP] = tmp.t_stopc;
|
|
tty->termios->c_cc[VEOF] = tmp.t_eofc;
|
|
tty->termios->c_cc[VEOF] = tmp.t_eofc;
|
|
tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
|
|
tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
|
|
|
|
+ mutex_unlock(&tty->termios_mutex);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
@@ -696,6 +702,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
|
|
{
|
|
{
|
|
struct ltchars tmp;
|
|
struct ltchars tmp;
|
|
|
|
|
|
|
|
+ mutex_lock(&tty->termios_mutex);
|
|
tmp.t_suspc = tty->termios->c_cc[VSUSP];
|
|
tmp.t_suspc = tty->termios->c_cc[VSUSP];
|
|
/* what is dsuspc anyway? */
|
|
/* what is dsuspc anyway? */
|
|
tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
|
|
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_flushc = tty->termios->c_cc[VEOL2];
|
|
tmp.t_werasc = tty->termios->c_cc[VWERASE];
|
|
tmp.t_werasc = tty->termios->c_cc[VWERASE];
|
|
tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
|
|
tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
|
|
|
|
+ mutex_unlock(&tty->termios_mutex);
|
|
return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
|
|
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)))
|
|
if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
+ mutex_lock(&tty->termios_mutex);
|
|
tty->termios->c_cc[VSUSP] = tmp.t_suspc;
|
|
tty->termios->c_cc[VSUSP] = tmp.t_suspc;
|
|
/* what is dsuspc anyway? */
|
|
/* what is dsuspc anyway? */
|
|
tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
|
|
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[VEOL2] = tmp.t_flushc;
|
|
tty->termios->c_cc[VWERASE] = tmp.t_werasc;
|
|
tty->termios->c_cc[VWERASE] = tmp.t_werasc;
|
|
tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
|
|
tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
|
|
|
|
+ mutex_unlock(&tty->termios_mutex);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|