Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 03 Sep 2019 14:08:11 -0000
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r346502 - stable/12/sys/dev/vt
Message-ID:  <201904212221.x3LMLawp021468@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sun Apr 21 22:21:36 2019
New Revision: 346502
URL: https://svnweb.freebsd.org/changeset/base/346502

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/12/sys/dev/vt/vt_core.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/vt/vt_core.c
==============================================================================
--- stable/12/sys/dev/vt/vt_core.c	Sun Apr 21 22:13:07 2019	(r346501)
+++ stable/12/sys/dev/vt/vt_core.c	Sun Apr 21 22:21:36 2019	(r346502)
@@ -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);
 }





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