fix console change race exposed by CFS
authorJan Lübbe <jluebbe@lasnet.de>
Sat, 29 Sep 2007 16:47:51 +0000 (18:47 +0200)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 29 Sep 2007 17:00:15 +0000 (10:00 -0700)
The new behaviour of CFS exposes a race which occurs if a switch is
requested when vt_mode.mode is VT_PROCESS.

The process with vc->vt_pid is signaled before vc->vt_newvt is set.
This causes the switch to fail when triggered by the monitoing process
because the target is still -1.

[ If the signal sending fails, the subsequent "reset_vc(vc)" will then
  reset vt_newvt to -1, so this works for that case too.   - Linus ]

Signed-off-by: Jan Lübbe <jluebbe@lasnet.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/vt_ioctl.c

index c6f6f42097391b20f434a669ae6b0f263fda63ee..045e6888d15baf60f421251f6ef6c881ec0996a5 100644 (file)
@@ -1208,15 +1208,18 @@ void change_console(struct vc_data *new_vc)
                /*
                 * Send the signal as privileged - kill_pid() will
                 * tell us if the process has gone or something else
-                * is awry
+                * is awry.
+                *
+                * We need to set vt_newvt *before* sending the signal or we
+                * have a race.
                 */
+               vc->vt_newvt = new_vc->vc_num;
                if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
                        /*
                         * It worked. Mark the vt to switch to and
                         * return. The process needs to send us a
                         * VT_RELDISP ioctl to complete the switch.
                         */
-                       vc->vt_newvt = new_vc->vc_num;
                        return;
                }