Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Apr 2019 13:55:06 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r346549 - stable/11/sys/dev/vt
Message-ID:  <201904221355.x3MDt6R9024755@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904221355.x3MDt6R9024755>