summaryrefslogtreecommitdiffstats
path: root/sys/dev/vt
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-05-08 16:19:01 +0000
committerhselasky <hselasky@FreeBSD.org>2015-05-08 16:19:01 +0000
commitd0e1b4c12cf60860efc7511197c3318bc313a44c (patch)
treead31a5e8a4fb371905838fb0b40e95286989cf78 /sys/dev/vt
parent57645743ad68104c4909f8b55254cdc2fff04293 (diff)
downloadFreeBSD-src-d0e1b4c12cf60860efc7511197c3318bc313a44c.zip
FreeBSD-src-d0e1b4c12cf60860efc7511197c3318bc313a44c.tar.gz
Prevent switching to NULL or own window in the "vt_proc_window_switch"
function. This fixes an issue where X11 keyboard input can appear stuck. The cause of the problem is a duplicate TTY device window switch IOCTL during boot, which leaves the "vt_switch_timer" running, because the current window is already selected. While at it factor out some NULL checks. PR: 200032 Differential Revision: https://reviews.freebsd.org/D2480 Reported by: several people MFC after: 1 week Reviewed by: emaste
Diffstat (limited to 'sys/dev/vt')
-rw-r--r--sys/dev/vt/vt_core.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index a637055..e6603a9 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -451,12 +451,35 @@ vt_proc_window_switch(struct vt_window *vw)
struct vt_device *vd;
int ret;
+ /* Prevent switching to NULL */
+ if (vw == NULL) {
+ DPRINTF(30, "%s: Cannot switch: vw is NULL.", __func__);
+ return (EINVAL);
+ }
vd = vw->vw_device;
curvw = vd->vd_curwindow;
+ /* Check if virtual terminal is locked */
if (curvw->vw_flags & VWF_VTYLOCK)
return (EBUSY);
+ /* Check if switch already in progress */
+ if (curvw->vw_flags & VWF_SWWAIT_REL) {
+ /* Check if switching to same window */
+ if (curvw->vw_switch_to == vw) {
+ DPRINTF(30, "%s: Switch in progress to same vw.", __func__);
+ return (0); /* success */
+ }
+ DPRINTF(30, "%s: Switch in progress to different vw.", __func__);
+ return (EBUSY);
+ }
+
+ /* Avoid switching to already selected window */
+ if (vw == curvw) {
+ DPRINTF(30, "%s: Cannot switch: vw == curvw.", __func__);
+ return (0); /* success */
+ }
+
/* Ask current process permission to switch away. */
if (curvw->vw_smode.mode == VT_PROCESS) {
DPRINTF(30, "%s: VT_PROCESS ", __func__);
@@ -664,8 +687,7 @@ vt_scrollmode_kbdevent(struct vt_window *vw, int c, int console)
if (console == 0) {
if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
vw = vd->vd_windows[c - F_SCR];
- if (vw != NULL)
- vt_proc_window_switch(vw);
+ vt_proc_window_switch(vw);
return;
}
VT_LOCK(vd);
@@ -750,8 +772,7 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
if (c >= F_SCR && c <= MIN(L_SCR, F_SCR + VT_MAXWINDOWS - 1)) {
vw = vd->vd_windows[c - F_SCR];
- if (vw != NULL)
- vt_proc_window_switch(vw);
+ vt_proc_window_switch(vw);
return (0);
}
@@ -760,15 +781,13 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c)
/* Switch to next VT. */
c = (vw->vw_number + 1) % VT_MAXWINDOWS;
vw = vd->vd_windows[c];
- if (vw != NULL)
- vt_proc_window_switch(vw);
+ vt_proc_window_switch(vw);
return (0);
case PREV:
/* Switch to previous VT. */
c = (vw->vw_number - 1) % VT_MAXWINDOWS;
vw = vd->vd_windows[c];
- if (vw != NULL)
- vt_proc_window_switch(vw);
+ vt_proc_window_switch(vw);
return (0);
case SLK: {
vt_save_kbd_state(vw, kbd);
@@ -2774,8 +2793,7 @@ vt_resume(struct vt_device *vd)
if (vt_suspendswitch == 0)
return;
- /* Switch back to saved window */
- if (vd->vd_savedwindow != NULL)
- vt_proc_window_switch(vd->vd_savedwindow);
+ /* Switch back to saved window, if any */
+ vt_proc_window_switch(vd->vd_savedwindow);
vd->vd_savedwindow = NULL;
}
OpenPOWER on IntegriCloud