Thread (20 messages) 20 messages, 4 authors, 2020-01-07

Re: BUG: unable to handle kernel NULL pointer dereference in mem_serial_out

From: Dmitry Vyukov <dvyukov@google.com>
Date: 2019-12-13 10:00:50
Also in: lkml

On Fri, Dec 13, 2019 at 10:34 AM Greg KH [off-list ref] wrote:
On Fri, Dec 13, 2019 at 10:02:33AM +0100, Dmitry Vyukov wrote:
quoted
On Thu, Dec 12, 2019 at 11:57 AM Greg KH [off-list ref] wrote:
quoted
On Fri, Dec 06, 2019 at 10:25:08PM -0800, syzbot wrote:
quoted
Hello,

syzbot found the following crash on:

HEAD commit:    7ada90eb Merge tag 'drm-next-2019-12-06' of git://anongit...
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=123ec282e00000
kernel config:  https://syzkaller.appspot.com/x/.config?x=f07a23020fd7d21a
dashboard link: https://syzkaller.appspot.com/bug?extid=f4f1e871965064ae689e
compiler:       gcc (GCC) 9.0.0 20181231 (experimental)
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=17ab090ee00000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=17f127f2e00000

IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+f4f1e871965064ae689e@syzkaller.appspotmail.com

BUG: kernel NULL pointer dereference, address: 0000000000000002
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
PGD 9764a067 P4D 9764a067 PUD 9f995067 PMD 0
Oops: 0002 [#1] PREEMPT SMP KASAN
CPU: 0 PID: 9687 Comm: syz-executor433 Not tainted 5.4.0-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
RIP: 0010:writeb arch/x86/include/asm/io.h:65 [inline]
RIP: 0010:mem_serial_out+0x70/0x90 drivers/tty/serial/8250/8250_port.c:408
Code: e9 00 00 00 49 8d 7c 24 40 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48
c1 ea 03 d3 e3 80 3c 02 00 75 19 48 63 db 49 03 5c 24 40 <44> 88 2b 5b 41 5c
41 5d 5d c3 e8 81 ed cf fd eb c0 e8 da ed cf fd
RSP: 0018:ffffc90001de78e8 EFLAGS: 00010202
RAX: dffffc0000000000 RBX: 0000000000000002 RCX: 0000000000000000
RDX: 1ffffffff181f40e RSI: ffffffff83e28776 RDI: ffffffff8c0fa070
RBP: ffffc90001de7900 R08: ffff8880919dc340 R09: ffffed10431ee1c6
R10: ffffed10431ee1c5 R11: ffff888218f70e2b R12: ffffffff8c0fa030
R13: 0000000000000001 R14: ffffc90001de7a40 R15: ffffffff8c0fa188
FS:  0000000001060880(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000002 CR3: 000000009e6b8000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
 serial_out drivers/tty/serial/8250/8250.h:118 [inline]
 serial8250_clear_fifos.part.0+0x3a/0xb0
drivers/tty/serial/8250/8250_port.c:557
 serial8250_clear_fifos drivers/tty/serial/8250/8250_port.c:556 [inline]
 serial8250_do_startup+0x426/0x1cf0 drivers/tty/serial/8250/8250_port.c:2121
 serial8250_startup+0x62/0x80 drivers/tty/serial/8250/8250_port.c:2329
 uart_port_startup drivers/tty/serial/serial_core.c:219 [inline]
 uart_startup drivers/tty/serial/serial_core.c:258 [inline]
 uart_startup+0x452/0x980 drivers/tty/serial/serial_core.c:249
 uart_set_info drivers/tty/serial/serial_core.c:998 [inline]
 uart_set_info_user+0x13b4/0x1cf0 drivers/tty/serial/serial_core.c:1023
 tty_tiocsserial drivers/tty/tty_io.c:2506 [inline]
 tty_ioctl+0xf60/0x14f0 drivers/tty/tty_io.c:2648
 vfs_ioctl fs/ioctl.c:47 [inline]
 file_ioctl fs/ioctl.c:545 [inline]
 do_vfs_ioctl+0x977/0x14e0 fs/ioctl.c:732
 ksys_ioctl+0xab/0xd0 fs/ioctl.c:749
 __do_sys_ioctl fs/ioctl.c:756 [inline]
 __se_sys_ioctl fs/ioctl.c:754 [inline]
 __x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:754
 do_syscall_64+0xfa/0x790 arch/x86/entry/common.c:294
 entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x440219
Code: 18 89 d0 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 48 89 f8 48 89 f7
48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff
0f 83 fb 13 fc ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007ffced648c78 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 0000000000440219
RDX: 0000000020000240 RSI: 000000000000541f RDI: 0000000000000003
RBP: 00000000006ca018 R08: 0000000000000000 R09: 00000000004002c8
R10: 0000000000401b30 R11: 0000000000000246 R12: 0000000000401aa0
R13: 0000000000401b30 R14: 0000000000000000 R15: 0000000000000000
Modules linked in:
CR2: 0000000000000002
---[ end trace eaa11ffe82f3a763 ]---
RIP: 0010:writeb arch/x86/include/asm/io.h:65 [inline]
RIP: 0010:mem_serial_out+0x70/0x90 drivers/tty/serial/8250/8250_port.c:408
Code: e9 00 00 00 49 8d 7c 24 40 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48
c1 ea 03 d3 e3 80 3c 02 00 75 19 48 63 db 49 03 5c 24 40 <44> 88 2b 5b 41 5c
41 5d 5d c3 e8 81 ed cf fd eb c0 e8 da ed cf fd
RSP: 0018:ffffc90001de78e8 EFLAGS: 00010202
RAX: dffffc0000000000 RBX: 0000000000000002 RCX: 0000000000000000
RDX: 1ffffffff181f40e RSI: ffffffff83e28776 RDI: ffffffff8c0fa070
RBP: ffffc90001de7900 R08: ffff8880919dc340 R09: ffffed10431ee1c6
R10: ffffed10431ee1c5 R11: ffff888218f70e2b R12: ffffffff8c0fa030
R13: 0000000000000001 R14: ffffc90001de7a40 R15: ffffffff8c0fa188
FS:  0000000001060880(0000) GS:ffff8880ae800000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000002 CR3: 000000009e6b8000 CR4: 00000000001406f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
You set up a dubious memory base for your uart and then get upset when
you write to that location.

I don't know what to really do about this, this is a root-only operation
and you are expected to know what you are doing when you attempt this.
Hi Greg,

Thanks for looking into this!
Should we restrict the fuzzer from accessing /dev/ttyS* entirely?
No, not at all.
quoted
Or only restrict TIOCSSERIAL on them? Something else?
Try running not as root.  if you have CAP_SYS_ADMIN you can do a lot of
pretty bad things with tty ports, as you see here.  There's a reason the
LOCKDOWN_TIOCSSERIAL "security lockdown" check was added :)

The TIOCSSERIAL ioctl is a nice one for a lot of things that are able to
be done as a normal user (baud rate changes, etc.), but there are also
things like setting io port memory locations that can cause random
hardware accesses and kernel crashes, as you instantly found out here :)

So restrict the fuzzer to only run as a "normal" user of the serial
port, and if you find problems there, I'll be glad to look at them.
Easier said than done. "normal user of the serial port" is not really
a thing in Linux, right? You either have CAP_SYS_ADMIN or not, that's
not per-device...
As far as I remember +Tetsuo proposed a config along the lines of
"restrict only things that legitimately cause damage under a fuzzer
workload", e.g. freezing filesystems, disabling console output, etc.
This may be another candidate. But I can't find where that proposal is
now.

A simpler option that I see is as follows. syzkaller has several
sandboxing modes, one of them is "namespace" which uses a user ns, in
that more fuzzer is still uid=0 in the init namespace, so has access
to all /dev nodes, but it does not have CAP_SYS_ADMIN in the init
namespace. We could enable /dev/ttyS* only on instance that use
sandbox=namesace, and disable on the rest. Does it make sense?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help