summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-05-21 07:34:08 +0000
committerhselasky <hselasky@FreeBSD.org>2015-05-21 07:34:08 +0000
commitc3358cbfc558db5f8b63e251a049e9c412ab151c (patch)
treeab2e6c5bc46ba234fcde5be9ab2dd38655ffee5b /sys
parentcbbe96a6ffee1b806bd553eeaa916bfa86e68178 (diff)
downloadFreeBSD-src-c3358cbfc558db5f8b63e251a049e9c412ab151c.zip
FreeBSD-src-c3358cbfc558db5f8b63e251a049e9c412ab151c.tar.gz
MFC r282645, r282646 and r282730:
* 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. * The "SYSCTL_INT()" default value is only used for read only SYSCTLs and is not applicable unless the integer pointer is NULL. Set it to zero to avoid confusion. While at it remove extra semicolon at the end of the "VT_SYSCTL_INT()" macro. * Ensure the result from signed subtraction under modulus does not become negative. PR: 200032
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/vt/vt.h6
-rw-r--r--sys/dev/vt/vt_core.c42
2 files changed, 33 insertions, 15 deletions
diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h
index ab291e6..05ae3e2 100644
--- a/sys/dev/vt/vt.h
+++ b/sys/dev/vt/vt.h
@@ -83,10 +83,10 @@
#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
#define VT_SYSCTL_INT(_name, _default, _descr) \
-static int vt_##_name = _default; \
-SYSCTL_INT(_kern_vt, OID_AUTO, _name, CTLFLAG_RW, &vt_##_name, _default,\
+static int vt_##_name = (_default); \
+SYSCTL_INT(_kern_vt, OID_AUTO, _name, CTLFLAG_RWTUN, &vt_##_name, 0, \
_descr); \
-TUNABLE_INT("kern.vt." #_name, &vt_##_name);
+TUNABLE_INT("kern.vt." #_name, &vt_##_name)
struct vt_driver;
diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c
index 9b723c8..eee7777 100644
--- a/sys/dev/vt/vt_core.c
+++ b/sys/dev/vt/vt_core.c
@@ -448,12 +448,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__);
@@ -661,8 +684,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);
@@ -747,8 +769,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);
}
@@ -757,15 +778,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;
+ c = (vw->vw_number + VT_MAXWINDOWS - 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);
@@ -2702,8 +2721,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