Author: ian
Date: Mon Dec 31 01:09:23 2018
New Revision: 342639
URL: https://svnweb.freebsd.org/changeset/base/342639

Log:
  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.
  
  Discussed with:            ray@

Modified:
  head/sys/dev/vt/vt_core.c

Modified: head/sys/dev/vt/vt_core.c
==============================================================================
--- head/sys/dev/vt/vt_core.c   Mon Dec 31 00:26:35 2018        (r342638)
+++ head/sys/dev/vt/vt_core.c   Mon Dec 31 01:09:23 2018        (r342639)
@@ -977,10 +977,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);
@@ -1011,6 +1023,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);
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to