diff options
-rw-r--r-- | drivers/char/selection.c | 2 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 29 | ||||
-rw-r--r-- | drivers/char/vt.c | 12 | ||||
-rw-r--r-- | drivers/char/vt_ioctl.c | 17 | ||||
-rw-r--r-- | include/linux/vt_kern.h | 3 |
5 files changed, 36 insertions, 27 deletions
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 71093a9fc462..74cff839c857 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -33,7 +33,7 @@ extern void poke_blanked_console(void); | |||
33 | 33 | ||
34 | /* Variables for selection control. */ | 34 | /* Variables for selection control. */ |
35 | /* Use a dynamic buffer, instead of static (Dec 1994) */ | 35 | /* Use a dynamic buffer, instead of static (Dec 1994) */ |
36 | struct vc_data *sel_cons; /* must not be disallocated */ | 36 | struct vc_data *sel_cons; /* must not be deallocated */ |
37 | static volatile int sel_start = -1; /* cleared by clear_selection */ | 37 | static volatile int sel_start = -1; /* cleared by clear_selection */ |
38 | static int sel_end; | 38 | static int sel_end; |
39 | static int sel_buffer_lth; | 39 | static int sel_buffer_lth; |
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 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 0fca83ededff..b49f03375439 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -885,8 +885,17 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
885 | return err; | 885 | return err; |
886 | } | 886 | } |
887 | 887 | ||
888 | int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | ||
889 | { | ||
890 | int rc; | ||
891 | |||
892 | acquire_console_sem(); | ||
893 | rc = vc_resize(vc, cols, lines); | ||
894 | release_console_sem(); | ||
895 | return rc; | ||
896 | } | ||
888 | 897 | ||
889 | void vc_disallocate(unsigned int currcons) | 898 | void vc_deallocate(unsigned int currcons) |
890 | { | 899 | { |
891 | WARN_CONSOLE_UNLOCKED(); | 900 | WARN_CONSOLE_UNLOCKED(); |
892 | 901 | ||
@@ -3790,6 +3799,7 @@ EXPORT_SYMBOL(default_blu); | |||
3790 | EXPORT_SYMBOL(update_region); | 3799 | EXPORT_SYMBOL(update_region); |
3791 | EXPORT_SYMBOL(redraw_screen); | 3800 | EXPORT_SYMBOL(redraw_screen); |
3792 | EXPORT_SYMBOL(vc_resize); | 3801 | EXPORT_SYMBOL(vc_resize); |
3802 | EXPORT_SYMBOL(vc_lock_resize); | ||
3793 | EXPORT_SYMBOL(fg_console); | 3803 | EXPORT_SYMBOL(fg_console); |
3794 | EXPORT_SYMBOL(console_blank_hook); | 3804 | EXPORT_SYMBOL(console_blank_hook); |
3795 | EXPORT_SYMBOL(console_blanked); | 3805 | EXPORT_SYMBOL(console_blanked); |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index a5628a8b6620..a53e382cc107 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -96,7 +96,7 @@ do_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_str | |||
96 | if (!perm) | 96 | if (!perm) |
97 | return -EPERM; | 97 | return -EPERM; |
98 | if (!i && v == K_NOSUCHMAP) { | 98 | if (!i && v == K_NOSUCHMAP) { |
99 | /* disallocate map */ | 99 | /* deallocate map */ |
100 | key_map = key_maps[s]; | 100 | key_map = key_maps[s]; |
101 | if (s && key_map) { | 101 | if (s && key_map) { |
102 | key_maps[s] = NULL; | 102 | key_maps[s] = NULL; |
@@ -819,20 +819,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
819 | if (arg > MAX_NR_CONSOLES) | 819 | if (arg > MAX_NR_CONSOLES) |
820 | return -ENXIO; | 820 | return -ENXIO; |
821 | if (arg == 0) { | 821 | if (arg == 0) { |
822 | /* disallocate all unused consoles, but leave 0 */ | 822 | /* deallocate all unused consoles, but leave 0 */ |
823 | acquire_console_sem(); | 823 | acquire_console_sem(); |
824 | for (i=1; i<MAX_NR_CONSOLES; i++) | 824 | for (i=1; i<MAX_NR_CONSOLES; i++) |
825 | if (! VT_BUSY(i)) | 825 | if (! VT_BUSY(i)) |
826 | vc_disallocate(i); | 826 | vc_deallocate(i); |
827 | release_console_sem(); | 827 | release_console_sem(); |
828 | } else { | 828 | } else { |
829 | /* disallocate a single console, if possible */ | 829 | /* deallocate a single console, if possible */ |
830 | arg--; | 830 | arg--; |
831 | if (VT_BUSY(arg)) | 831 | if (VT_BUSY(arg)) |
832 | return -EBUSY; | 832 | return -EBUSY; |
833 | if (arg) { /* leave 0 */ | 833 | if (arg) { /* leave 0 */ |
834 | acquire_console_sem(); | 834 | acquire_console_sem(); |
835 | vc_disallocate(arg); | 835 | vc_deallocate(arg); |
836 | release_console_sem(); | 836 | release_console_sem(); |
837 | } | 837 | } |
838 | } | 838 | } |
@@ -847,11 +847,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
847 | if (get_user(ll, &vtsizes->v_rows) || | 847 | if (get_user(ll, &vtsizes->v_rows) || |
848 | get_user(cc, &vtsizes->v_cols)) | 848 | get_user(cc, &vtsizes->v_cols)) |
849 | return -EFAULT; | 849 | return -EFAULT; |
850 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 850 | for (i = 0; i < MAX_NR_CONSOLES; i++) |
851 | acquire_console_sem(); | 851 | vc_lock_resize(vc_cons[i].d, cc, ll); |
852 | vc_resize(vc_cons[i].d, cc, ll); | ||
853 | release_console_sem(); | ||
854 | } | ||
855 | return 0; | 852 | return 0; |
856 | } | 853 | } |
857 | 854 | ||
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 918a29763aea..1009d3fe1fc2 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h | |||
@@ -33,7 +33,8 @@ extern int fg_console, last_console, want_console; | |||
33 | int vc_allocate(unsigned int console); | 33 | int vc_allocate(unsigned int console); |
34 | int vc_cons_allocated(unsigned int console); | 34 | int vc_cons_allocated(unsigned int console); |
35 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); | 35 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); |
36 | void vc_disallocate(unsigned int console); | 36 | int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines); |
37 | void vc_deallocate(unsigned int console); | ||
37 | void reset_palette(struct vc_data *vc); | 38 | void reset_palette(struct vc_data *vc); |
38 | void do_blank_screen(int entering_gfx); | 39 | void do_blank_screen(int entering_gfx); |
39 | void do_unblank_screen(int leaving_gfx); | 40 | void do_unblank_screen(int leaving_gfx); |