/* Variables for selection control. */
 /* Use a dynamic buffer, instead of static (Dec 1994) */
-struct vc_data *sel_cons;              /* must not be disallocated */
+struct vc_data *sel_cons;              /* must not be deallocated */
 static volatile int sel_start = -1;    /* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
 
  *     actually has driver level meaning and triggers a VC resize.
  *
  *     Locking:
- *             The console_sem is used to ensure we do not try and resize
- *     the console twice at once.
- *     FIXME: Two racing size sets may leave the console and kernel
- *             parameters disagreeing. Is this exploitable ?
- *     FIXME: Random values racing a window size get is wrong
- *     should lock here against that
+ *             Called function use the console_sem is used to ensure we do
+ *     not try and resize the console twice at once.
+ *             The tty->termios_sem is used to ensure we don't double
+ *     resize and get confused. Lock order - tty->termios.sem before
+ *     console sem
  */
 
 static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
 
        if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
                return -EFAULT;
+
+       down(&tty->termios_sem);
        if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
-               return 0;
+               goto done;
+
 #ifdef CONFIG_VT
        if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
-               int rc;
-
-               acquire_console_sem();
-               rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
-               release_console_sem();
-               if (rc)
-                       return -ENXIO;
+               if (vc_lock_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row)) {
+                       up(&tty->termios_sem);
+                       return -ENXIO;
+               }
        }
 #endif
        if (tty->pgrp > 0)
                kill_pg(real_tty->pgrp, SIGWINCH, 1);
        tty->winsize = tmp_ws;
        real_tty->winsize = tmp_ws;
+done:
+       up(&tty->termios_sem);
        return 0;
 }
 
 
        return err;
 }
 
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
+{
+       int rc;
+
+       acquire_console_sem();
+       rc = vc_resize(vc, cols, lines);
+       release_console_sem();
+       return rc;
+}
 
-void vc_disallocate(unsigned int currcons)
+void vc_deallocate(unsigned int currcons)
 {
        WARN_CONSOLE_UNLOCKED();
 
 EXPORT_SYMBOL(update_region);
 EXPORT_SYMBOL(redraw_screen);
 EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(vc_lock_resize);
 EXPORT_SYMBOL(fg_console);
 EXPORT_SYMBOL(console_blank_hook);
 EXPORT_SYMBOL(console_blanked);
 
                if (!perm)
                        return -EPERM;
                if (!i && v == K_NOSUCHMAP) {
-                       /* disallocate map */
+                       /* deallocate map */
                        key_map = key_maps[s];
                        if (s && key_map) {
                            key_maps[s] = NULL;
                if (arg > MAX_NR_CONSOLES)
                        return -ENXIO;
                if (arg == 0) {
-                   /* disallocate all unused consoles, but leave 0 */
+                   /* deallocate all unused consoles, but leave 0 */
                        acquire_console_sem();
                        for (i=1; i<MAX_NR_CONSOLES; i++)
                                if (! VT_BUSY(i))
-                                       vc_disallocate(i);
+                                       vc_deallocate(i);
                        release_console_sem();
                } else {
-                       /* disallocate a single console, if possible */
+                       /* deallocate a single console, if possible */
                        arg--;
                        if (VT_BUSY(arg))
                                return -EBUSY;
                        if (arg) {                            /* leave 0 */
                                acquire_console_sem();
-                               vc_disallocate(arg);
+                               vc_deallocate(arg);
                                release_console_sem();
                        }
                }
                if (get_user(ll, &vtsizes->v_rows) ||
                    get_user(cc, &vtsizes->v_cols))
                        return -EFAULT;
-               for (i = 0; i < MAX_NR_CONSOLES; i++) {
-                       acquire_console_sem();
-                       vc_resize(vc_cons[i].d, cc, ll);
-                       release_console_sem();
-               }
+               for (i = 0; i < MAX_NR_CONSOLES; i++)
+                       vc_lock_resize(vc_cons[i].d, cc, ll);
                return 0;
        }
 
 
 int vc_allocate(unsigned int console);
 int vc_cons_allocated(unsigned int console);
 int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
-void vc_disallocate(unsigned int console);
+int vc_lock_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
+void vc_deallocate(unsigned int console);
 void reset_palette(struct vc_data *vc);
 void do_blank_screen(int entering_gfx);
 void do_unblank_screen(int leaving_gfx);