diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index eb881cfa53e0..2a1e95b0f282 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -2770,12 +2770,11 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg) | |||
2770 | * actually has driver level meaning and triggers a VC resize. | 2770 | * actually has driver level meaning and triggers a VC resize. |
2771 | * | 2771 | * |
2772 | * Locking: | 2772 | * Locking: |
2773 | * The console_sem is used to ensure we do not try and resize | 2773 | * Called function use the console_sem is used to ensure we do |
2774 | * the console twice at once. | 2774 | * not try and resize the console twice at once. |
2775 | * FIXME: Two racing size sets may leave the console and kernel | 2775 | * The tty->termios_sem is used to ensure we don't double |
2776 | * parameters disagreeing. Is this exploitable ? | 2776 | * resize and get confused. Lock order - tty->termios.sem before |
2777 | * FIXME: Random values racing a window size get is wrong | 2777 | * console sem |
2778 | * should lock here against that | ||
2779 | */ | 2778 | */ |
2780 | 2779 | ||
2781 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | 2780 | static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, |
@@ -2785,17 +2784,17 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | |||
2785 | 2784 | ||
2786 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) | 2785 | if (copy_from_user(&tmp_ws, arg, sizeof(*arg))) |
2787 | return -EFAULT; | 2786 | return -EFAULT; |
2787 | |||
2788 | down(&tty->termios_sem); | ||
2788 | if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) | 2789 | if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg))) |
2789 | return 0; | 2790 | goto done; |
2791 | |||
2790 | #ifdef CONFIG_VT | 2792 | #ifdef CONFIG_VT |
2791 | if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) { | 2793 | if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) { |
2792 | int rc; | 2794 | if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row)) { |
2793 | 2795 | up(&tty->termios_sem); | |
2794 | acquire_console_sem(); | 2796 | return -ENXIO; |
2795 | rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row); | 2797 | } |
2796 | release_console_sem(); | ||
2797 | if (rc) | ||
2798 | return -ENXIO; | ||
2799 | } | 2798 | } |
2800 | #endif | 2799 | #endif |
2801 | if (tty->pgrp > 0) | 2800 | if (tty->pgrp > 0) |
@@ -2804,6 +2803,8 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, | |||
2804 | kill_pg(real_tty->pgrp, SIGWINCH, 1); | 2803 | kill_pg(real_tty->pgrp, SIGWINCH, 1); |
2805 | tty->winsize = tmp_ws; | 2804 | tty->winsize = tmp_ws; |
2806 | real_tty->winsize = tmp_ws; | 2805 | real_tty->winsize = tmp_ws; |
2806 | done: | ||
2807 | up(&tty->termios_sem); | ||
2807 | return 0; | 2808 | return 0; |
2808 | } | 2809 | } |
2809 | 2810 | ||