• P
    [PATCH] Remove race between con_open and con_close · f786648b
    Paul Mackerras 提交于
    [ Same race and same patch also by Steven Rostedt <rostedt@goodmis.org> ]
    
    I have a laptop (G3 powerbook) which will pretty reliably hit a race
    between con_open and con_close late in the boot process and oops in
    vt_ioctl due to tty->driver_data being NULL.
    
    What happens is this: process A opens /dev/tty6; it comes into
    con_open() (drivers/char/vt.c) and assign a non-NULL value to
    tty->driver_data.  Then process A closes that and concurrently process
    B opens /dev/tty6.  Process A gets through con_close() and clears
    tty->driver_data, since tty->count == 1.  However, before process A
    can decrement tty->count, we switch to process B (e.g. at the
    down(&tty_sem) call at drivers/char/tty_io.c line 1626).
    
    So process B gets to run and comes into con_open with tty->count == 2,
    as tty->count is incremented (in init_dev) before con_open is called.
    Because tty->count != 1, we don't set tty->driver_data.  Then when the
    process tries to do anything with that fd, it oopses.
    
    The simple and effective fix for this is to test tty->driver_data
    rather than tty->count in con_open.  The testing and setting of
    tty->driver_data is serialized with respect to the clearing of
    tty->driver_data in con_close by the console_sem.  We can't get a
    situation where con_open sees tty->driver_data != NULL and then
    con_close on a different fd clears tty->driver_data, because
    tty->count is incremented before con_open is called.  Thus this patch
    eliminates the race, and in fact with this patch my laptop doesn't
    oops.
    Signed-off-by: NPaul Mackerras <paulus@samba.org>
    [ Same patch
    Signed-off-by: NSteven Rostedt <rostedt@goodmis.org>
      in http://marc.theaimsgroup.com/?l=linux-kernel&m=112450820432121&w=2 ]
    Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
    f786648b
vt.c 77.9 KB