]> git.hungrycats.org Git - linux/commitdiff
[PATCH] fix console oops/race
authorAndrew Morton <akpm@osdl.org>
Sat, 20 Mar 2004 01:45:57 +0000 (17:45 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sat, 20 Mar 2004 01:45:57 +0000 (17:45 -0800)
Finally nailed this sucker.

con_close() checks the tty->count and then sleeps in acquire_console_sem().
But another process can come in and grab a ref against the tty while
con_close() dropped the BKL.  But con_close() then proceeds to deallocate the
tty->driver_data anyway, even though the tty now has ->count == 2.

Fix that by moving the check for ->tty_count inside console_sem.

drivers/char/vt.c

index edc8c46fed6bf61289fdb610eb4039a281bcc650..2b3965c06999d5c0f85dd218e87d945e4d56babf 100644 (file)
@@ -2481,19 +2481,18 @@ static int con_open(struct tty_struct *tty, struct file * filp)
        return 0;
 }
 
-static void con_close(struct tty_struct *tty, struct file * filp)
+static void con_close(struct tty_struct *tty, struct file *filp)
 {
-       struct vt_struct *vt;
-       
-       if (!tty || tty->count != 1)
-               return;
-
-       vcs_remove_devfs(tty);
        acquire_console_sem();
-       vt = (struct vt_struct*)tty->driver_data;
-       if (vt)
-               vc_cons[vt->vc_num].d->vc_tty = NULL;
-       tty->driver_data = 0;
+       if (tty && tty->count == 1) {
+               struct vt_struct *vt;
+
+               vcs_remove_devfs(tty);
+               vt = tty->driver_data;
+               if (vt)
+                       vc_cons[vt->vc_num].d->vc_tty = NULL;
+               tty->driver_data = 0;
+       }
        release_console_sem();
 }