Skip to content

Commit ee0c1a6

Browse files
peterhurleygregkh
authored andcommitted
tty: Fix tty_send_xchar() lock order inversion
The correct lock order is atomic_write_lock => termios_rwsem, as established by tty_write() => n_tty_write(). Fixes: c274f6e ("tty: Hold termios_rwsem for tcflow(TCIxxx)") Reported-and-Tested-by: Dmitry Vyukov <[email protected]> Cc: <[email protected]> # v3.18+ Signed-off-by: Peter Hurley <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8005c49 commit ee0c1a6

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

drivers/tty/tty_io.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,18 +1282,22 @@ int tty_send_xchar(struct tty_struct *tty, char ch)
12821282
int was_stopped = tty->stopped;
12831283

12841284
if (tty->ops->send_xchar) {
1285+
down_read(&tty->termios_rwsem);
12851286
tty->ops->send_xchar(tty, ch);
1287+
up_read(&tty->termios_rwsem);
12861288
return 0;
12871289
}
12881290

12891291
if (tty_write_lock(tty, 0) < 0)
12901292
return -ERESTARTSYS;
12911293

1294+
down_read(&tty->termios_rwsem);
12921295
if (was_stopped)
12931296
start_tty(tty);
12941297
tty->ops->write(tty, &ch, 1);
12951298
if (was_stopped)
12961299
stop_tty(tty);
1300+
up_read(&tty->termios_rwsem);
12971301
tty_write_unlock(tty);
12981302
return 0;
12991303
}

drivers/tty/tty_ioctl.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,16 +1147,12 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
11471147
spin_unlock_irq(&tty->flow_lock);
11481148
break;
11491149
case TCIOFF:
1150-
down_read(&tty->termios_rwsem);
11511150
if (STOP_CHAR(tty) != __DISABLED_CHAR)
11521151
retval = tty_send_xchar(tty, STOP_CHAR(tty));
1153-
up_read(&tty->termios_rwsem);
11541152
break;
11551153
case TCION:
1156-
down_read(&tty->termios_rwsem);
11571154
if (START_CHAR(tty) != __DISABLED_CHAR)
11581155
retval = tty_send_xchar(tty, START_CHAR(tty));
1159-
up_read(&tty->termios_rwsem);
11601156
break;
11611157
default:
11621158
return -EINVAL;

0 commit comments

Comments
 (0)