kernel BUG and freeze on cat /proc/tty/driver/serial
Hello,
reading /proc/tty/driver/serial leads to a NULL pointer dereference BUG and freeze on a serial-console enabled 2.6.35.{4,10,11} and 2.6.37. 2.6.32.28 does fine without BUG and freeze.
Fresh boot 2.6.35.11 into emergency...
# cat /proc/tty/driver/serial [ 73.199568] BUG: unable to handle kernel NULL pointer dereference at 00000099 [ 73.227373] IP: [<c11a8969>] tty_ldisc_try+0x10/0x35 [ 73.227373] *pdpt = 0000000036da6001 *pde = 0000000000000000 [ 73.227373] Oops: 0000 [#1] SMP [ 73.227373] last sysfs file: /sys/devices/virtual/block/md1/md/level [ 73.227373] Modules linked in: ext2 mbcache aes_i586 aes_generic xts gf128mul dm_crypt raid1 md_mod dm_mirror dm_region_hash dm_log btrfs zlib_deflate crc32c libcrc32c dm_mod usbhid hid sg sr_mod sd_mod cdrom crc_t10dif ata_generic uhci_hcd ahci ehci_hcd pata_jmicron libahci firewire_ohci sata_sil24 libata firewire_core crc_itu_t floppy usbcore thermal scsi_mod atl1 thermal_sys mii nls_base [last unloaded: scsi_wait_scan] [ 73.227373] [ 73.227373] Pid: 857, comm: cat Not tainted 2.6.35.11 #1 P5E-V HDMI/P5E-V HDMI [ 73.227373] EIP: 0060:[<c11a8969>] EFLAGS: 00010046 CPU: 3 [ 73.227373] EIP is at tty_ldisc_try+0x10/0x35 [ 73.227373] EAX: 00000002 EBX: 00000000 ECX: c156779c EDX: 000003fe [ 73.227373] ESI: 00000000 EDI: f6c40000 EBP: 0000009b ESP: f6f39e9c [ 73.227373] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 73.227373] Process cat (pid: 857, ti=f6f38000 task=f6a05280 task.ti=f6f38000) [ 73.227373] Stack: [ 73.227373] c1569a08 f6ccc000 c11c4d9d c1569a08 00000080 f6ccc000 c139d488 c1569a08 [ 73.227373] <0> f6ccc000 f6c40000 f6f39eec c11c4f76 c11c2b36 00000000 000003f8 c139d482 [ 73.227373] <0> 00000000 00000000 f6c40040 c142fae4 0804e3f0 fff77270 c5b3a560 c143a444 [ 73.227373] Call Trace: [ 73.227373] [<c11c4d9d>] ? check_modem_status+0x7d/0x170 [ 73.227373] [<c11c4f76>] ? serial8250_get_mctrl+0x5/0x35 [ 73.227373] [<c11c2b36>] ? uart_proc_show+0x134/0x2ea [ 73.227373] [<c10d077c>] ? seq_read+0x176/0x336 [ 73.227373] [<c10a460f>] ? handle_mm_fault+0xbd5/0xc06 [ 73.227373] [<c10d0606>] ? seq_read+0x0/0x336 [ 73.227373] [<c10efc4d>] ? proc_reg_read+0x55/0x68 [ 73.227373] [<c10efbf8>] ? proc_reg_read+0x0/0x68 [ 73.227373] [<c10bd133>] ? vfs_read+0x7c/0xd7 [ 73.227373] [<c128c475>] ? do_page_fault+0x26d/0x2cf [ 73.227373] [<c10bd221>] ? sys_read+0x3c/0x60 [ 73.227373] [<c1007d5f>] ? sysenter_do_call+0x12/0x28 [ 73.227373] Code: 00 eb ea ff 47 4c 89 fb 89 ea b8 9c 77 56 c1 e8 7c 0e 0e 00 89 d8 5b 5e 5f 5d c3 56 89 c6 53 b8 9c 77 56 c1 e8 21 0e 0e 00 31 db <f6> 86 99 00 00 00 02 74 0b 8b 5e 28 85 db 74 04 f0 ff 43 04 89 [ 73.227373] EIP: [<c11a8969>] tty_ldisc_try+0x10/0x35 SS:ESP 0068:f6f39e9c [ 73.227373] CR2: 0000000000000099 [ 73.227373] ---[ end trace d434316c12adce41 ]---
2.6.37 doesn't print a full trace before freezing but only the first two lines or less.
Either disabling the serial console or running setserial -g on the serial console port avoids the BUG and the freeze:
Fresh boot 2.6.35.11 into emergency...
# setserial -g /dev/ttyS0 /dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4 # cat /proc/tty/driver/serial serinfo:1.0 driver revision: 0: uart:16550A port:000003F8 irq:4 tx:0 rx:0 CTS|DTR|CD 1: uart:unknown port:000002F8 irq:3 2: uart:unknown port:000003E8 irq:4 3: uart:unknown port:000002E8 irq:3 4: uart:16550A port:0000EC00 irq:17 tx:0 rx:0 5: uart:16550A port:0000E880 irq:17 tx:0 rx:0 CTS|CD 6: uart:16550A port:0000E800 irq:17 tx:0 rx:0 7: uart:16550A port:0000E480 irq:17 tx:0 rx:0 8: uart:16550A port:0000E400 irq:17 tx:0 rx:0 9: uart:16550A port:0000E080 irq:17 tx:0 rx:0 #
serial and console related kernel boot messages:
[ 0.000000] Kernel command line: BOOT_IMAGE=/vmlinuz-2.6.35.11 root=/dev/mapper/md1 ro console=ttyS0,38400n8r console=tty0 enable_mtrr_cleanup raid=noautodetect parport=0x378,7,3 8250.nr_uarts=10 panic=60 emergency [ 0.000000] Console: colour dummy device 80x25 [ 0.000000] console [tty0] enabled [ 0.000000] console [ttyS0] enabled [ 3.391406] vesafb: framebuffer at 0xd0000000, mapped to 0xf8280000, using 3072k, total 3072k [ 3.416943] vesafb: mode is 1024x768x32, linelength=4096, pages=0 [ 3.435193] vesafb: scrolling: redraw [ 3.446167] vesafb: Truecolor: size=8:8:8:8, shift=24:16:8:0 [ 3.482257] Console: switching to colour frame buffer device 128x48 [ 3.520338] fb0: VESA VGA frame buffer device [ 3.955642] Serial: 8250/16550 driver, 10 ports, IRQ sharing enabled [ 3.974981] serial8250: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A [ 3.993496] 00:0a: ttyS0 at I/O 0x3f8 (irq = 4) is a 16550A [ 4.010472] serial 0000:05:01.0: PCI INT A -> GSI 17 (level, low) -> IRQ 17 [ 4.031637] 0000:05:01.0: ttyS4 at I/O 0xec00 (irq = 17) is a 16550A [ 4.050966] 0000:05:01.0: ttyS5 at I/O 0xe880 (irq = 17) is a 16550A [ 4.070282] 0000:05:01.0: ttyS6 at I/O 0xe800 (irq = 17) is a 16550A [ 4.089608] 0000:05:01.0: ttyS7 at I/O 0xe480 (irq = 17) is a 16550A [ 4.108940] 0000:05:01.0: ttyS8 at I/O 0xe400 (irq = 17) is a 16550A [ 4.128258] 0000:05:01.0: ttyS9 at I/O 0xe080 (irq = 17) is a 16550A
regards
Mario
Signature · 4 lines
Computer games don't affect kids; I mean if Pac-Man affected us as kids,
we'd all be running around in darkened rooms, munching magic pills and
listening to repetitive electronic music.
-- Kristian Wilson, Nintendo Inc, 1989Hello,
Quoted 3 lines · Mario 'BitKoenig' Holbe
reading
/proc/tty/driver/serialleads to a NULL pointer dereference BUG and freeze on a serial-console enabled 2.6.35.{4,10,11} and 2.6.37. 2.6.32.28 does fine without BUG and freeze.
This issue persists with 2.6.37.3 and 2.6.38-rc8.
regards
Mario
Signature · 2 lines
Good, Fast, Cheap: Pick any two (you can't have all three).
-- RFC 1925, 7aQuoted 8 lines · On Wed, 16 Feb 2011 17:17:28 +0100 "Mario 'BitKoenig' Holbe"…
reading
/proc/tty/driver/serialleads to a NULL pointer dereference BUG and freeze on a serial-console enabled 2.6.35.{4,10,11} and 2.6.37. 2.6.32.28 does fine without BUG and freeze.Fresh boot 2.6.35.11 into emergency...
# cat /proc/tty/driver/serial [ 73.199568] BUG: unable to handle kernel NULL pointer dereference at 00000099 [ 73.227373] IP: [<c11a8969>] tty_ldisc_try+0x10/0x35
The oops is here, in uart_handle_dcd_change() in serial_core.h:
struct tty_ldisc *ld = tty_ldisc_ref(port->tty);
(port->tty is NULL)
Called from check_modem_status() in 8250.c:
if (status & UART_MSR_DDCD)
uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);
So apparently the port has no tty, until you run "setserial -g", or else that somehow makes the DCD status appear unchanged later when reading /proc/tty/driver/serial.
2011/3/10 Chuck Ebbert <[email protected]>:
Quoted 18 lines
Quoted 8 lines · On Wed, 16 Feb 2011 17:17:28 +0100 "Mario 'BitKoenig' Holbe"…
reading
/proc/tty/driver/serialleads to a NULL pointer dereference BUG and freeze on a serial-console enabled 2.6.35.{4,10,11} and 2.6.37. 2.6.32.28 does fine without BUG and freeze.Fresh boot 2.6.35.11 into emergency...
# cat /proc/tty/driver/serial [ 73.199568] BUG: unable to handle kernel NULL pointer dereference at 00000099 [ 73.227373] IP: [<c11a8969>] tty_ldisc_try+0x10/0x35The oops is here, in
uart_handle_dcd_change()inserial_core.h:struct
tty_ldisc*ld =tty_ldisc_ref(port->tty);(
port->ttyis NULL)
Quoted 8 lines
Called from
check_modem_status()in 8250.c:if (status &
UART_MSR_DDCD)uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);So apparently the port has no tty, until you run "setserial -g", or else that somehow makes the DCD status appear unchanged later when reading
/proc/tty/driver/serial.
Just noticed the same freeze of my box with 3.1.0-rc4 - thought with just a little bit different stack trace
(as I've taken only camera snap - here is just list of function) - happened right after resume.
tty_ldisc_try NULL pointer dereference
tty_ldisc_refcheck_modem_statusserial8250_get_mctrluart_proc_show
? seq_read
? kmem_cache_alloc_trace
? seq_readseq_read
? sub_preempt_count
? seq_lseekproc_reg_readvfs_readsys_readsystem_call_fastpath
Zdenek
2011/9/2 Zdenek Kabelac <[email protected]>:
Quoted 36 lines
2011/3/10 Chuck Ebbert <[email protected]>:
Quoted 18 lines
Quoted 8 lines · On Wed, 16 Feb 2011 17:17:28 +0100 "Mario 'BitKoenig' Holbe"…
reading
/proc/tty/driver/serialleads to a NULL pointer dereference BUG and freeze on a serial-console enabled 2.6.35.{4,10,11} and 2.6.37. 2.6.32.28 does fine without BUG and freeze.Fresh boot 2.6.35.11 into emergency...
# cat /proc/tty/driver/serial [ 73.199568] BUG: unable to handle kernel NULL pointer dereference at 00000099 [ 73.227373] IP: [<c11a8969>] tty_ldisc_try+0x10/0x35The oops is here, in
uart_handle_dcd_change()inserial_core.h:struct
tty_ldisc*ld =tty_ldisc_ref(port->tty);(
port->ttyis NULL)Quoted 8 lines
Called from
check_modem_status()in 8250.c:if (status &
UART_MSR_DDCD)uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);So apparently the port has no tty, until you run "setserial -g", or else that somehow makes the DCD status appear unchanged later when reading
/proc/tty/driver/serial.Just noticed the same freeze of my box with 3.1.0-rc4 - thought with just a little bit different stack trace
(as I've taken only camera snap - here is just list of function) - happened right after resume.
tty_ldisc_tryNULL pointer dereference
Quoted 14 lines
tty_ldisc_refcheck_modem_statusserial8250_get_mctrluart_proc_show
?seq_read
?kmem_cache_alloc_trace
?seq_readseq_read
?sub_preempt_count
?seq_lseekproc_reg_readvfs_readsys_readsystem_call_fastpath
Anything new about this issue ?
Seems I'm getting recently several of those reports with 3.4 kernel:
tty_ldisc_refuart_handle_dcd_change
Even something simple like this:
drivers/tty/serial/serial_core.c +0 -0
@@ -2453,7 +2453,7 @@ void uart_handle_dcd_change(struct uart_port
*uport, unsigned int status)
{
struct uart_state *state = uport->state;
struct tty_port *port = &state->port;
- struct tty_ldisc *ld = tty_ldisc_ref(port->tty);
+ struct tty_ldisc *ld = port ? tty_ldisc_ref(port->tty) : NULL;
struct pps_event_time ts;
if (ld && ld->ops->dcd_change)
@@ -2465,7 +2465,7 @@ void uart_handle_dcd_change(struct uart_port
*uport, unsigned int status)
hardpps();#endif
- if (port->flags & ASYNC_CHECK_CD) {
+ if (port && port->flags & ASYNC_CHECK_CD) {
if (status)
wake_up_interruptible(&port->open_wait);
else if (port->tty)Zdenek
Quoted 14 lines
(quoted diff) +2
-2- struct tty_ldisc *ld = tty_ldisc_ref(port->tty); + struct tty_ldisc *ld = port ? tty_ldisc_ref(port->tty) : NULL; struct pps_event_time ts; if (ld && ld->ops->dcd_change)@@ -2465,7 +2465,7 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status) hardpps(); #endif - if (port->flags & ASYNC_CHECK_CD) { + if (port && port->flags & ASYNC_CHECK_CD) { if (status) wake_up_interruptible(&port->open_wait);
Quoted 1 line
else if (port->tty)
Probably should be using tty krefs for this
tty = tty_port_tty_get( ..) / tty_kref_put
etc, and yes the NULL check is needed. The reference is needed so the tty can't be freed under you.
2012/5/25 Alan Cox <[email protected]>:
Quoted 18 lines
Quoted 14 lines
- struct
tty_ldisc*ld =tty_ldisc_ref(port->tty);
+ structtty_ldisc*ld = port ?tty_ldisc_ref(port->tty): NULL; structpps_event_timets;if (ld &&
ld->ops->dcd_change)(quoted diff) +1
-1@@ -2465,7 +2465,7 @@ void uart_handle_dcd_change(struct uart_port *uport, unsigned int status) hardpps(); #endif - if (port->flags & ASYNC_CHECK_CD) { + if (port && port->flags & ASYNC_CHECK_CD) { if (status) wake_up_interruptible(&port->open_wait);Quoted 1 line
else if (
port->tty)Probably should be using tty krefs for this
Quoted 7 lines
tty =
tty_port_tty_get( ..)/ tty_kref_putetc, and yes the NULL check is needed. The reference is needed so the tty can't be freed under you.
So you mean something like this ?
(going to test it)
Subject: [PATCH 6/6] tty check
--- drivers/tty/serial/serial_core.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/tty/serial/serial_core.c +2 -2
@@ -2452,8 +2452,8 @@ EXPORT_SYMBOL(uart_match_port);void uart_handle_dcd_change (struct uart_port *uport,unsigned int status) {struct uart_state *state = uport->state; -struct tty_port *port = &state->port; -struct tty_ldisc *ld =tty_ldisc_ref (port->tty); +struct tty_struct *tty =tty_port_tty_get (&state->port); +struct tty_ldisc *ld = (tty) ?tty_ldisc_ref (tty) :NULL ;struct pps_event_time ts;if (ld && ld->ops->dcd_change)
@@ -2465,17 +2465,19 @@ void uart_handle_dcd_change(struct uart_port
*uport, unsigned int status)
hardpps();
#endif
- if (port->flags & ASYNC_CHECK_CD) {
+ if (tty && (tty->flags & ASYNC_CHECK_CD)) {
if (status)
- wake_up_interruptible(&port->open_wait);
- else if (port->tty)
- tty_hangup(port->tty);
+ wake_up_interruptible(&state->port.open_wait);
+ else
+ tty_hangup(tty);
}
if (ld && ld->ops->dcd_change)
- ld->ops->dcd_change(port->tty, status, &ts);
+ ld->ops->dcd_change(tty, status, &ts);
if (ld)
tty_ldisc_deref(ld);
+ if (tty)
+ tty_kref_put(tty);
}
EXPORT_SYMBOL_GPL(uart_handle_dcd_change);