Re: Bug report - slab-out-of-bounds in vcs_scr_readw

From: Greg KH
Date: Mon Nov 04 2019 - 10:24:45 EST


On Mon, Nov 04, 2019 at 04:39:55AM -0800, Or Cohen wrote:
> Hi,
> I discovered a OOB access bug using Syzkaller and decided to report it,
> as I could not find a similar report in syzkaller mailing list,
> syzkaller-bugs mailing list
> or syzbot dashboard. ( as described in:
> https://github.com/google/syzkaller/blob/master/docs/linux/reporting_kernel_bugs.md
> )
>
> I've tested it and the bug reproduces on the following versions:
>
> commit 4d856f72c10ecb060868ed10ff1b1453943fc6c8 (HEAD, tag: v5.3)
> Author: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
> Date: Sun Sep 15 14:19:32 2019 -0700
> Linux 5.3
>
> commit 84df9525b0c27f3ebc2ebb1864fa62a97fdedb7d (grafted, HEAD, tag: v4.19)
> Author: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
> Date: Mon Oct 22 07:37:37 2018 +0100
> Linux 4.19
>
> The call stack at the time of the crash is as follows: (kernel 5.3)
> __dump_stack lib/dump_stack.c:77 [inline]
> dump_stack+0x88/0xce lib/dump_stack.c:113
> print_address_description+0x60/0x31f mm/kasan/report.c:351
> __kasan_report.cold.6+0x1a/0x3c mm/kasan/report.c:482
> kasan_report+0xe/0x12 mm/kasan/common.c:618
> vcs_scr_readw+0xb1/0xc0 drivers/tty/vt/vt.c:4665
> vcs_write+0x5c2/0xbb0 drivers/tty/vt/vc_screen.c:545
> do_loop_readv_writev fs/read_write.c:717 [inline]
> do_loop_readv_writev fs/read_write.c:701 [inline]
> do_iter_write fs/read_write.c:972 [inline]
> do_iter_write+0x47b/0x5f0 fs/read_write.c:951
> vfs_writev+0x1b3/0x2f0 fs/read_write.c:1015
> do_writev+0x11f/0x2e0 fs/read_write.c:1058
> do_syscall_64+0xb7/0x3a0 arch/x86/entry/common.c:296
> entry_SYSCALL_64_after_hwframe+0x44/0xa9
>
>
> The overwritten buffer is of size 4000 bytes and is allocated in:
> vc_allocate+0x3b0/0x6d0 drivers/tty/vt/vt.c:1098
>
> >From my brief analysis of the "vcs_write" function ( vc_screen.c ), it
> seems like the
> "screen_pos" function (line 548) is used to return a pointer into the
> overwritten buffer:
>
> 540: while (this_round > 0) {
> 541: unsigned char c = *con_buf0++;
> 542:
> 543: this_round--;
> 544: vcs_scr_writew(vc,
> 545: vcs_scr_readw(vc, org) & 0xff00) | c, org);
> 546: org++;
> 547: if (++col == maxcol) {
> 548: org = screen_pos(vc, p, viewed);
> 549: col = 0;
> 550: p += maxcol;
> 551: }
> 552: }
>
> The "count" argument ( controlled from user space ) affects the
> initialization
> of "this_round".
> After several iterations of the while loop, "screen_pos" returns a pointer
> to offset
> 4000 into the buffer which leads KASAN to detect it as an OOB read of 2
> bytes in "vcs_scr_readw".
> We can see however, that immediately after that "vcs_scr_writew" is called
> which
> leads to a write of 2 bytes past the end of the buffer.
>
> The following files are attached:
> repro.c - A C reproducer for the bug.

Your repo.c file is "interesting" saying you have a giant buffer, yet it
really is just 1 byte long. Does that have something to do with the
problem here?

I am at another conference at the moment and can't look at this much
now, will try to later this week...

thanks,

greg k-h