f786648b89
[ 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: Paul Mackerras <paulus@samba.org> [ Same patch Signed-off-by: Steven Rostedt <rostedt@goodmis.org> in http://marc.theaimsgroup.com/?l=linux-kernel&m=112450820432121&w=2 ] Signed-off-by: Linus Torvalds <torvalds@osdl.org> |
||
---|---|---|
.. | ||
agp | ||
drm | ||
ftape | ||
ip2 | ||
ipmi | ||
mwave | ||
pcmcia | ||
rio | ||
tpm | ||
watchdog | ||
amiserial.c | ||
applicom.c | ||
applicom.h | ||
cd1865.h | ||
ChangeLog | ||
consolemap.c | ||
cp437.uni | ||
cyclades.c | ||
decserial.c | ||
defkeymap.c_shipped | ||
defkeymap.map | ||
digi1.h | ||
digi.h | ||
digiFep1.h | ||
digiPCI.h | ||
ds1286.c | ||
ds1302.c | ||
ds1620.c | ||
dsp56k.c | ||
dtlk.c | ||
ec3104_keyb.c | ||
efirtc.c | ||
epca.c | ||
epca.h | ||
epcaconfig.h | ||
esp.c | ||
generic_nvram.c | ||
generic_serial.c | ||
genrtc.c | ||
hangcheck-timer.c | ||
hpet.c | ||
hvc_console.c | ||
hvc_vio.c | ||
hvcs.c | ||
hvsi.c | ||
hw_random.c | ||
i8k.c | ||
ip2.c | ||
ip2main.c | ||
ip27-rtc.c | ||
isicom.c | ||
istallion.c | ||
ite_gpio.c | ||
Kconfig | ||
keyboard.c | ||
lcd.c | ||
lcd.h | ||
lp.c | ||
Makefile | ||
mbcs.c | ||
mbcs.h | ||
mem.c | ||
misc.c | ||
mmtimer.c | ||
moxa.c | ||
mxser.c | ||
mxser.h | ||
n_hdlc.c | ||
n_r3964.c | ||
n_tty.c | ||
nvram.c | ||
nwbutton.c | ||
nwbutton.h | ||
nwflash.c | ||
ppdev.c | ||
pty.c | ||
qtronix.c | ||
qtronixmap.c_shipped | ||
qtronixmap.map | ||
random.c | ||
raw.c | ||
riscom8_reg.h | ||
riscom8.c | ||
riscom8.h | ||
rocket_int.h | ||
rocket.c | ||
rocket.h | ||
rtc.c | ||
s3c2410-rtc.c | ||
scan_keyb.c | ||
scan_keyb.h | ||
scc.h | ||
scx200_gpio.c | ||
selection.c | ||
ser_a2232.c | ||
ser_a2232.h | ||
ser_a2232fw.ax | ||
ser_a2232fw.h | ||
serial167.c | ||
snsc_event.c | ||
snsc.c | ||
snsc.h | ||
sonypi.c | ||
specialix_io8.h | ||
specialix.c | ||
stallion.c | ||
sx.c | ||
sx.h | ||
sxboards.h | ||
sxwindow.h | ||
synclink.c | ||
synclinkmp.c | ||
sysrq.c | ||
tb0219.c | ||
tipar.c | ||
toshiba.c | ||
tty_io.c | ||
tty_ioctl.c | ||
vc_screen.c | ||
viocons.c | ||
viotape.c | ||
vme_scc.c | ||
vr41xx_giu.c | ||
vr41xx_rtc.c | ||
vt_ioctl.c | ||
vt.c |