Author: ian
Date: Mon Apr 22 13:55:06 2019
New Revision: 346549
URL: https://svnweb.freebsd.org/changeset/base/346549

Log:
  MFC r342639:
  
  When allocating a new keyboard at vt_upgrade() time, unwind any cngrabs
  done on the old keyboard and then do the corresponding number of grabs
  on the new keyboard.
  
  This fixes a race that can leave the system with a non-functioning
  keyboard.  It goes like this...
  
   - The bios claims there is an AT keyboard, atkbd attaches.
   - SI_SUB_INT_CONFIG_HOOKS runs.
   - USB probes devices. Devices begin attaching, including disks.
   - GELI prompts for a password for a just-attached disk, which results
     in a cngrab() while atkbd is the keyboard.
   - A USB keyboard attaches.
   - vt_upgrade() runs and switches the keyboard to the new USB keyboard,
     but because cngrab was never called for it, it's not activated and
     keystrokes are ignored.
   - Now there is no functional keyboard and no way to get one; even
     plugging in a different USB keyboard doesn't help, because the console
     is still grabbed, still waiting for a GELI pw.

Modified:
  stable/11/sys/dev/vt/vt_core.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/vt/vt_core.c
==============================================================================
--- stable/11/sys/dev/vt/vt_core.c      Mon Apr 22 13:51:25 2019        
(r346548)
+++ stable/11/sys/dev/vt/vt_core.c      Mon Apr 22 13:55:06 2019        
(r346549)
@@ -937,10 +937,22 @@ vt_kbdevent(keyboard_t *kbd, int event, void *arg)
 static int
 vt_allocate_keyboard(struct vt_device *vd)
 {
-       int              idx0, idx;
+       int              grabbed, i, idx0, idx;
        keyboard_t      *k0, *k;
        keyboard_info_t  ki;
 
+       /*
+        * If vt_upgrade() happens while the console is grabbed, we are
+        * potentially going to switch keyboard devices while the keyboard is in
+        * use. Unwind the grabbing of the current keyboard first, then we will
+        * re-grab the new keyboard below, before we return.
+        */
+       if (vd->vd_curwindow == &vt_conswindow) {
+               grabbed = vd->vd_curwindow->vw_grabbed;
+               for (i = 0; i < grabbed; ++i)
+                       vtterm_cnungrab(vd->vd_curwindow->vw_terminal);
+       }
+
        idx0 = kbd_allocate("kbdmux", -1, vd, vt_kbdevent, vd);
        if (idx0 >= 0) {
                DPRINTF(20, "%s: kbdmux allocated, idx = %d\n", __func__, idx0);
@@ -971,6 +983,11 @@ vt_allocate_keyboard(struct vt_device *vd)
        }
        vd->vd_keyboard = idx0;
        DPRINTF(20, "%s: vd_keyboard = %d\n", __func__, vd->vd_keyboard);
+
+       if (vd->vd_curwindow == &vt_conswindow) {
+               for (i = 0; i < grabbed; ++i)
+                       vtterm_cngrab(vd->vd_curwindow->vw_terminal);
+       }
 
        return (idx0);
 }


_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to