Re: uart_start NULL pointer dereference

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 05/19/2015 08:10 PM, Elliott, Robert (Server Storage) wrote:
> I accidentally pasted a huge bunch of text to the linux serial port and
> triggered a NULL pointer dereference in the kernel (4.0).  I have not 
> tried to replicate it again.

Wow, sorry this took me so long to figure out what was going on; mostly because I
found a mess of bugs trying to reproduce this problem.

I wrote a reproducer where the sender continually sends data (with flow
control disabled) and the receiver opens, reads some data, and closes without
stopping the sender, all while echoing the received data.

The cause of the warning below is fixed by "serial: core: Fix crashes while
echoing when closing". The patch changelog details the cause and cure.

Regards,
Peter Hurley


> Serial port/console log:
> 
> [    0.000000] Kernel command line: ... console=ttyS1,115200 console=tty0 ...
> ...
> Login incorrect
> [  136.234321] BUG: unable to handle kernel NULL pointer dereference at 00000000000001f4
> [  136.238938] IP: [<ffffffff81384a5a>] __uart_start.isra.7+0x1a/0x50
> [  136.242441] PGD 0
> [  136.243597] Oops: 0000 [#1] SMP
> [  136.245494] Modules linked in: nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack xt_mark iptable_filter ip_tables bridge stp llc vfat fat x86_pkg_temp_thermal coretemp kvm_intel kvm crc32c_intel ghash_clmulni_intel aesni_intel aes_x86_64 glue_helper lrw gf128mul ablk_helper cryptd microcode iTCO_wdt iTCO_vendor_support lpc_ich hpwdt mfd_core nd_btt nd_pmem xhci_pci i2c_i801 xhci_hcd sb_edac edac_core hpilo ioatdma shpchp pcspkr dca pcc_cpufreq nfsd wmi nd_acpi acpi_cpufreq libnd auth_rpcgss nfs_acl lockd grace sunrpc uinput xfs exportfs sr_mod sd_mod cdrom bnx2x tg3 ahci libahci mdio ptp pps_core hpsa libcrc32c dm_mirror dm_region_hash dm_log dm_mod ipv6 autofs4 efivarfs
> [  136.283067] CPU: 6 PID: 917 Comm: kworker/u80:4 Not tainted 4.0.0+ #40
> [  136.286613] Hardware name: HP ProLiant DL380 Gen9
> [  136.290418] Workqueue: events_unbound flush_to_ldisc
> [  136.293136] task: ffff880851361c80 ti: ffff88084e918000 task.ti: ffff88084e918000
> [  136.297360] RIP: 0010:[<ffffffff81384a5a>]  [<ffffffff81384a5a>] __uart_start.isra.7+0x1a/0x50
> [  136.302409] RSP: 0018:ffff88084e91bc70  EFLAGS: 00010046
> [  136.305359] RAX: 0000000000000000 RBX: ffffffff8202e6f8 RCX: 0000000000009392
> [  136.309398] RDX: 0000000093929392 RSI: 000000000000006e RDI: ffffffff8202e6f8
> [  136.313367] RBP: ffff88084e91bc98 R08: ffffc9000a297000 R09: 0000000000000004
> [  136.317274] R10: 0000000000000004 R11: 000000000000006e R12: ffff880852013c00
> [  136.321383] R13: 0000000000000296 R14: ffffc9000a2992b0 R15: ffff88083dc7951b
> [  136.325311] FS:  0000000000000000(0000) GS:ffff88085f0c0000(0000) knlGS:0000000000000000
> [  136.329803] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [  136.332929] CR2: 00000000000001f4 CR3: 0000000001a0b000 CR4: 00000000001407e0
> [  136.336857] Stack:
> [  1368089]  ffffffff81384acb ffff88083dc795f7 00000000000000fe 0000000000000200
> [  136.442636]  ffff880852013c00 ffff88084e91bca8 ffffffff81384afe ffff88084e91bcd8
> [  136.446771]  ffffffff8136a82d 0000000000000000 ffff880852013c00 ffff88083dc7961c
> [  136.451410] Call Trace:
> [  136.452662]  [<ffffffff81384acb>] ? uart_start+0x3b/0x60
> [  136.455698]  [<ffffffff81384afe>] uart_flush_chars+0xe/0x10
> [  136.458920]  [<ffffffff8136a82d>] commit_echoes+0x8d/0xa0
> [  136.461919]  [<ffffffff8136d16f>] n_tty_receive_buf_common+0x7df/0xba0
> [  136.465537]  [<ffffffff8136d544>] n_tty_receive_buf2+0x14/0x20
> [  136.468793]  [<ffffffff813700bd>] flush_to_ldisc+0xdd/0x120
> [  136.471915]  [<ffffffff8106c292>] process_one_work+0x142/0x3f0
> [  136.475722]  [<ffffffff8106c65b>] worker_thread+0x11b/0x460
> [  136.478894]  [<ffffffff8106c540>] ? process_one_work+0x3f0/0x3f0
> [  136.482537]  [<ffffffff81071b49>] kthread+0xc9/0xe0
> [  136.485442]  [<ffffffff81071a80>] ? kthread_create_on_node+0x170/0x170
> [  136.489074]  [<ffffffff815b7b52>] ret_from_fork+0x42/0x70
> [  136.492058]  [<ffffffff81071a80>] ? kthread_create_on_node+0x170/0x170
> [  136.495745] Code: 41 5d 41 5e 41 5f 5d c3 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 8b bf 90 01 00 00 48 8b 87 a0 00 00 00 48 8b 80 90 00 00 00 <f6> 80 f4 01 00 00 01 74 05 c3 0f 1f 40 00 8b 87 f0 00 00 00 85
> [  136.507964] RIP  [<ffffffff81384a5a>] __uart_start.isra.7+0x1a/0x50
> [  136.511829]  RSP <ffff88084e91bc70>
> [  136.513813] CR2: 00000000000001f4
> 
> The instruction that crashed is at 19da, trying to dereference
> 	port->state->port.tty
> for the stopped bit.
> 
> 00000000000019c0 <__uart_start.isra.7>:
>     19c0:       e8 00 00 00 00          callq  19c5 <__uart_start.isra.7+0x5>
>                         19c1: R_X86_64_PC32     __fentry__-0x4
>     19c5:       48 8b bf 90 01 00 00    mov    0x190(%rdi),%rdi		
>     19cc:       48 8b 87 a0 00 00 00    mov    0xa0(%rdi),%rax		 
>     19d3:       48 8b 80 90 00 00 00    mov    0x90(%rax),%rax		 
>     19da:       f6 80 f4 01 00 00 01    testb  $0x1,0x1f4(%rax)		
>     19e1:       74 05                   je     19e8 <__uart_start.isra.7+0x28>
>     19e3:       c3                      retq
>     19e4:       0f 1f 40 00             nopl   0x0(%rax)
>     19e8:       8b 87 f0 00 00 00       mov    0xf0(%rdi),%eax
>     19ee:       85 c0                   test   %eax,%eax
>     19f0:       75 f1                   jne    19e3 <__uart_start.isra.7+0x23>
> 
> # offset 0x190=400 into struct uart_state		*port = state->uart_port
> # offset 0xa0=160 into struct uart_port		port->state
> # offset 0x90=144 into struct uart_state 		port->state->port.tty
> # offset 0x1f4=500 into struct_tty_struct		probably the stopped bit (NULL deref)
> 
> 
> drivers/tty/serial/serial_core.c:
> static void __uart_start(struct tty_struct *tty)
> {
>         struct uart_state *state = tty->driver_data;
>         struct uart_port *port = state->uart_port;
> 
>         if (!uart_tx_stopped(port))
>                 port->ops->start_tx(port);
> }
> 
> include/linux/serial_core.h:
> static inline int uart_tx_stopped(struct uart_port *port)
> {
>         struct tty_struct *tty = port->state->port.tty;
>         if (tty->stopped || port->hw_stopped)
>                 return 1;
>         return 0;
> }


--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux