Bug 209697

Summary: BUG: KASAN: use-after-free in do_update_region
Product: Drivers Reporter: rucsesec
Component: Console/FramebuffersAssignee: James Simmons (jsimmons)
Status: NEW ---    
Severity: normal    
Priority: P1    
Hardware: x86-64   
OS: Linux   
Kernel Version: v5.9.0 Subsystem:
Regression: No Bisected commit-id:
Attachments: Linux kernel config
C reproduce code

Description rucsesec 2020-10-15 07:53:32 UTC
Linux Kernel 5.9.0 - do_update_region use-after-free

0x01 - Introduction

===

Product: Linux Kernel 
Version: 5.9.0 and probably other versions
Bug: UAF (Read)
Tested on: GNU/Linux Debian 9 x86_64

0x02 - Details

===

There is a UAF read in the do_update_region function from /drivers/tty/vt/vt.c.
Code analysis (/drivers/tty/vt/vt.c: do_update_region()):

static void do_update_region(struct vc_data *vc, unsigned long start, int count)
{
	unsigned int xx, yy, offset;
	u16 *p;

	p = (u16 *) start;
	if (!vc->vc_sw->con_getxy) {
		offset = (start - vc->vc_origin) / 2;
		xx = offset % vc->vc_cols;
		yy = offset / vc->vc_cols;
	} else {
		int nxx, nyy;
		start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy);
		xx = nxx; yy = nyy;
	}
	for(;;) {
		u16 attrib = scr_readw(p) & 0xff00;
		int startx = xx;
		u16 *q = p;
		while (xx < vc->vc_cols && count) {
			if (attrib != (scr_readw(p) & 0xff00)) {  <=====  UAF occurs here (line: 663)
				if (p > q)
					vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
				startx = xx;
				q = p;
				attrib = scr_readw(p) & 0xff00;
			}
			p++;
			xx++;
			count--;
		}
		if (p > q)
			vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
		if (!count)
			break;
		xx = 0;
		yy++;
		if (vc->vc_sw->con_getxy) {
			p = (u16 *)start;
			start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
		}
	}
}

0x03 - Crash report

===

==================================================================
BUG: KASAN: use-after-free in do_update_region+0x525/0x5f0 /drivers/tty/vt/vt.c:663
Read of size 2 at addr ffff888000100000 by task systemd/1

CPU: 1 PID: 1 Comm: systemd Not tainted 5.9.0 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
Call Trace:
__dump_stack /lib/dump_stack.c:77 [inline]
dump_stack+0x9c/0xde /lib/dump_stack.c:118
print_address_description.constprop.0+0x1c/0x210 /mm/kasan/report.c:383
__kasan_report /mm/kasan/report.c:513 [inline]
kasan_report.cold+0x37/0x7c /mm/kasan/report.c:530
do_update_region+0x525/0x5f0 /drivers/tty/vt/vt.c:663
csi_J+0x294/0xa10 /drivers/tty/vt/vt.c:1568
do_con_trol+0x1e37/0x5270 /drivers/tty/vt/vt.c:2418 [inline]
do_con_write+0xc3c/0x19f0 /drivers/tty/vt/vt.c:2906
con_write+0x21/0xa0 /drivers/tty/vt/vt.c:3250
process_output_block /drivers/tty/n_tty.c:595 [inline]
n_tty_write+0x371/0xd60 /drivers/tty/n_tty.c:2333
do_tty_write /drivers/tty/tty_io.c:962 [inline]
tty_write+0x437/0x790 /drivers/tty/tty_io.c:1046
vfs_write+0x1d4/0x5f0 /fs/read_write.c:584
ksys_write+0x100/0x210 /fs/read_write.c:639
do_syscall_64+0x33/0x40 /arch/x86/entry/common.c:46
entry_SYSCALL_64_after_hwframe+0x44/0xa9
RIP: 0033:0x7fee913781b0
Code: 2e 0f 1f 84 00 00 00 00 00 90 48 8b 05 19 7e 20 00 c3 0f 1f 84 00 00 00 00 00 83 3d 19 c2 20 00 00 75 10 b8 01 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 31 c3 48 83 ec 08 e8 ae fc ff ff 48 89 04 24
RSP: 002b:00007ffc3cf30308 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 000000000000000a RCX: 00007fee913781b0
RDX: 000000000000000a RSI: 00007fee927e3cbe RDI: 0000000000000013
RBP: 00007fee927e3cbe R08: 00007ffc3cf302c0 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000013
R13: 0000000000000000 R14: ffffffffffffffff R15: 000055ea8fbf6810

 The buggy address belongs to the page:
 page:0000000070ff88e5 refcount:0 mapcount:-128 mapping:0000000000000000 index:0x0
pfn:0x100
 flags: 0x0()
 raw: 0000000000000000 ffff88807ffdc300 ffff88807ffdc300 0000000000000000
 raw: 0000000000000000 0000000000000008 00000000ffffff7f 0000000000000000
 page dumped because: kasan: bad access detected
 
 Memory state around the buggy address:
  ffff8880000fff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  ffff8880000fff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 >ffff888000100000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
                    ^
  ffff888000100080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  ffff888000100100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
 ==================================================================
Comment 1 rucsesec 2020-10-15 07:57:10 UTC
Created attachment 292979 [details]
Linux kernel config
Comment 2 rucsesec 2020-10-15 08:04:17 UTC
Created attachment 292981 [details]
C reproduce code