Skip to content

Commit

Permalink
n_tty: Fix unsafe driver-side signals
Browse files Browse the repository at this point in the history
An ldisc reference is insufficient guarantee the foreground process
group is not in the process of being signalled from a hangup.

1) Reads of tty->pgrp must be locked with ctrl_lock
2) The group pid must be referenced for the duration of signalling.
   Because the driver-side is not process-context, a pid reference
   must be acquired.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Peter Hurley authored and Greg Kroah-Hartman committed Mar 18, 2013
1 parent e91e52e commit 8c985d1
Showing 1 changed file with 14 additions and 20 deletions.
34 changes: 14 additions & 20 deletions drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,23 +1017,19 @@ static void eraser(unsigned char c, struct tty_struct *tty)
* isig - handle the ISIG optio
* @sig: signal
* @tty: terminal
* @flush: force flush
*
* Called when a signal is being sent due to terminal input. This
* may caus terminal flushing to take place according to the termios
* settings and character used. Called from the driver receive_buf
* path so serialized.
* Called when a signal is being sent due to terminal input.
* Called from the driver receive_buf path so serialized.
*
* Locking: ctrl_lock, read_lock (both via flush buffer)
* Locking: ctrl_lock
*/

static inline void isig(int sig, struct tty_struct *tty, int flush)
static inline void isig(int sig, struct tty_struct *tty)
{
if (tty->pgrp)
kill_pgrp(tty->pgrp, sig, 1);
if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
tty_driver_flush_buffer(tty);
struct pid *tty_pgrp = tty_get_pgrp(tty);
if (tty_pgrp) {
kill_pgrp(tty_pgrp, sig, 1);
put_pid(tty_pgrp);
}
}

Expand All @@ -1054,7 +1050,11 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
if (I_IGNBRK(tty))
return;
if (I_BRKINT(tty)) {
isig(SIGINT, tty, 1);
isig(SIGINT, tty);
if (!L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
tty_driver_flush_buffer(tty);
}
return;
}
if (I_PARMRK(tty)) {
Expand Down Expand Up @@ -1221,11 +1221,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
signal = SIGTSTP;
if (c == SUSP_CHAR(tty)) {
send_signal:
/*
* Note that we do not use isig() here because we want
* the order to be:
* 1) flush, 2) echo, 3) signal
*/
if (!L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
tty_driver_flush_buffer(tty);
Expand All @@ -1236,8 +1231,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
echo_char(c, tty);
process_echoes(tty);
}
if (tty->pgrp)
kill_pgrp(tty->pgrp, signal, 1);
isig(signal, tty);
return;
}
}
Expand Down

0 comments on commit 8c985d1

Please sign in to comment.