diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2006-09-29 05:00:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-29 12:18:12 -0400 |
commit | ca9bda00b4aafc42cd3d1b9d32934463e2993b4c (patch) | |
tree | dbb7ba5320bb8d1cbf97b3493687cb87932ad5f4 /drivers/char/tty_io.c | |
parent | ae78bf9c4f5fde3c67e2829505f195d7347ce3e4 (diff) |
[PATCH] tty locking on resize
The current kernel serializes console resizes but does not serialize the
resize against the tty structure updates. This means that while two
parallel resizes cannot mess up the console you can get incorrect results
reported.
Secondly while doing this I added vc_lock_resize() to lock and resize the
console. This leaves all knowledge of the console_sem in the vt/console
driver and kicks it out of the tty layer, which is good
Thirdly while doing this I decided I couldn't stand "disallocate" any
longer so I switched it to "deallocate".
Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Paul Fulghum <paulkf@microgate.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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 | ||