Skip to content
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
CVE/CVE-2019-19378/
CVE/CVE-2019-19378/

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 

CVE-2019-19378

Target

Linux Kernel btrfs FileSystem

Linux Version Availablity
5.0.21 True

Bug Type

slab-out-of-bounds write

Abstract

mounting crafted image can cause slab-out-of-bounds write in index_rbio_pages

it can be not only local(mount btrfs image in local shell), but also remote(mount corrupted(with crafted btrfs image) USB or other storage)

Reproduce

mkdir mnt
mount poc_2019_19378.img ./mnt

Details

Debug view

────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x0000000000000000  →  0x0000000000000000
$rbx   : 0x0000000000001000  →  0x0000000000001000
$rcx   : 0xffff88806b90ae38  →  0x0000000000000000  →  0x0000000000000000
$rdx   : 0xffffea0001b04e80  →  0x010000000000a016  →  0x010000000000a016
$rsp   : 0xffff88806c62fc20  →  0xffff88806b90ac88  →  0xffff888069bd5700  →  0x0000000200000001  →  0x0000000200000001
$rbp   : 0x0000000000001000  →  0x0000000000001000
$rsi   : 0x0000000000000000  →  0x0000000000000000
$rdi   : 0xffff88806b90ae38  →  0x0000000000000000  →  0x0000000000000000
$rip   : 0xffffffff81bc11d1  →  0x5c8b4cff957edae8  →  0x5c8b4cff957edae8
$r8    : 0x000000000000000c  →  0x000000000000000c
$r9    : 0xffffed100d1883aa  →  0x0000000000000000  →  0x0000000000000000
$r10   : 0xffff88806b90ac80  →  0xffff88806a634400  →  0x1e44a09cf7d0cbce  →  0x1e44a09cf7d0cbce
$r11   : 0xffffed100d7215af  →  0x0000000000000000  →  0x0000000000000000
$r12   : 0x0000000000000000  →  0x0000000000000000
$r13   : 0xdffffc0000000000  →  0xdffffc0000000000
$r14   : 0x0000000000000000  →  0x0000000000000000
$r15   : 0xffff888068c41cf0  →  0xffff888068c41b70  →  0x0000000000000000  →  0x0000000000000000
$eflags: [zero carry PARITY adjust SIGN trap interrupt direction overflow resume virtualx86 identification]
$cs: 0x0010 $ss: 0x0018 $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffff88806c62fc20│+0x0000: 0xffff88806b90ac88  →  0xffff888069bd5700  →  0x0000000200000001  →  0x0000000200000001	 ← $rsp
0xffff88806c62fc28│+0x0008: 0xffff888068c41d50  →  0xffff888067cde600  →  0xffffea0001b04e80  →  0x010000000000a016  →  0x010000000000a016
0xffff88806c62fc30│+0x0010: 0xffff88806b90ad18  →  0x0000000000000001  →  0x0000000000000001
0xffff88806c62fc38│+0x0018: 0xffff88806b90ad78  →  0xffff88806b90add8  →  0x0000000000000000  →  0x0000000000000000
0xffff88806c62fc40│+0x0020: 0xffff88806b90ae38  →  0x0000000000000000  →  0x0000000000000000
0xffff88806c62fc48│+0x0028: 0xffffea0001b04e80  →  0x010000000000a016  →  0x010000000000a016
0xffff88806c62fc50│+0x0030: 0x0000000000000000  →  0x0000000000000000
0xffff88806c62fc58│+0x0038: 0xffffffff00000000  →  0xffffffff00000000
──────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0xffffffff81bc11c2 <index_rbio_pages+1282> mov    QWORD PTR [rsp+0x30], rax
   0xffffffff81bc11c7 <index_rbio_pages+1287> mov    QWORD PTR [rsp+0x28], rdx
   0xffffffff81bc11cc <index_rbio_pages+1292> mov    QWORD PTR [rsp+0x20], rcx
 → 0xffffffff81bc11d1 <index_rbio_pages+1297> call   0xffffffff815190b0 <__asan_report_store8_noabort>
   ↳  0xffffffff815190b0 <__asan_report_store8_noabort+0> mov    rcx, QWORD PTR [rsp]
      0xffffffff815190b4 <__asan_report_store8_noabort+4> mov    edx, 0x1
      0xffffffff815190b9 <__asan_report_store8_noabort+9> mov    esi, 0x8
      0xffffffff815190be <__asan_report_store8_noabort+14> jmp    0xffffffff815185f0 <kasan_report>
      0xffffffff815190c3                  nop    DWORD PTR [rax]
      0xffffffff815190c6                  nop    WORD PTR cs:[rax+rax*1+0x0]
────────────────────────────────────────────────────────────────────────────────────────── arguments ────
__asan_report_store8_noabort (
   long unsigned int var_0 = 0xffff88806b90ae38 → 0x0000000000000000 → 0x0000000000000000
)
──────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "", stopped, reason: BREAKPOINT
[#1] Id 2, Name: "", stopped, reason: BREAKPOINT
────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0xffffffff81bc11d1 → index_rbio_pages(rbio=0xffff88806b90ac80)
[#1] 0xffffffff81bcba99 → raid56_rmw_stripe(rbio=<optimized out>)
[#2] 0xffffffff81bcba99 → rmw_work(work=0xffff88806b90acb0)
[#3] 0xffffffff81aecaaf → normal_work_helper(work=0xffff88806b90acb0)
[#4] 0xffffffff8115fed0 → process_one_work(worker=0xffff88806cfdf100, work=0xffff88806b90acc8)
[#5] 0xffffffff8116184a → worker_thread(__worker=0xffff88806cfdf100)
[#6] 0xffffffff811712f9 → kthread(_create=<optimized out>)
[#7] 0xffffffff83800215 → ret_from_fork()
─────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  p i
$24 = 0x0
gef➤  p page_index
$25 = 0xc
gef➤

when local variable i = zero and page_index = 0xc, out-of-bound write occurs in rbio->bio_pages array.

Bug causes

fs/btrfs/raid56.c:1163 (link)

static void index_rbio_pages(struct btrfs_raid_bio *rbio)
{
	struct bio *bio;
	u64 start;
	unsigned long stripe_offset;
	unsigned long page_index;

	spin_lock_irq(&rbio->bio_list_lock);
	bio_list_for_each(bio, &rbio->bio_list) {
		struct bio_vec bvec;
		struct bvec_iter iter;
		int i = 0;

		start = (u64)bio->bi_iter.bi_sector << 9;
		stripe_offset = start - rbio->bbio->raid_map[0];
[1]		page_index = stripe_offset >> PAGE_SHIFT;

		if (bio_flagged(bio, BIO_CLONED))
			bio->bi_iter = btrfs_io_bio(bio)->iter;

		bio_for_each_segment(bvec, bio, iter) {
[2]			rbio->bio_pages[page_index + i] = bvec.bv_page;
			i++;
		}
	}
	spin_unlock_irq(&rbio->bio_list_lock);
}

local variable page_index becomes 0xc[1], rbio->bio_pages array occurs slab-out-of-bounds write in [2].

KASAN logs

[  158.837964] ==================================================================
[  158.837964] BUG: KASAN: slab-out-of-bounds in index_rbio_pages+0x516/0x800
[  158.837964] Write of size 8 at addr ffff88806b90ae38 by task kworker/u4:1/20
[  158.837964]
[  158.837964] CPU: 0 PID: 20 Comm: kworker/u4:1 Not tainted 5.0.21 #1
[  158.837964] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[  158.837964] Workqueue: btrfs-rmw btrfs_rmw_helper
[  158.837964] Call Trace:
[  158.837964]  dump_stack+0x5b/0x8b
[  158.837964]  print_address_description+0x70/0x280
[  158.837964]  ? index_rbio_pages+0x516/0x800
[  158.837964]  kasan_report+0x13a/0x19b
[  158.837964]  ? index_rbio_pages+0x516/0x800
[  158.837964]  ? index_rbio_pages+0x516/0x800
[  158.837964]  index_rbio_pages+0x516/0x800
[  158.837964]  rmw_work+0xb9/0x650
[  158.837964]  ? __switch_to_asm+0x41/0x70
[  158.837964]  ? __switch_to_asm+0x35/0x70
[  158.837964]  ? __switch_to_asm+0x41/0x70
[  158.837964]  ? validate_rbio_for_rmw+0xd0/0xd0
[  158.837964]  ? __switch_to_asm+0x35/0x70
[  158.837964]  ? __switch_to_asm+0x41/0x70
[  158.837964]  ? __switch_to_asm+0x35/0x70
[  158.837964]  ? __switch_to_asm+0x41/0x70
[  158.837964]  ? __switch_to_asm+0x35/0x70
[  158.837964]  normal_work_helper+0x1cf/0xa50
[  158.837964]  ? read_word_at_a_time+0xe/0x20
[  158.837964]  ? strscpy+0x95/0x310
[  158.837964]  process_one_work+0x580/0x1210
[  158.837964]  worker_thread+0x8a/0xfc0
[  158.837964]  ? __kthread_parkme+0x73/0xf0
[  158.837964]  ? rescuer_thread+0xc60/0xc60
[  158.837964]  kthread+0x2a9/0x390
[  158.837964]  ? kthread_destroy_worker+0x90/0x90
[  158.837964]  ret_from_fork+0x35/0x40
[  158.837964]
[  158.837964] Allocated by task 1863:
[  158.837964]  __kasan_kmalloc+0xd5/0xf0
[  158.837964]  alloc_rbio+0xb3/0x890
[  158.837964]  raid56_parity_write+0x22/0x440
[  158.837964]  btrfs_map_bio+0x982/0xd50
[  158.837964]  btree_submit_bio_hook+0x246/0x2a0
[  158.837964]  submit_one_bio+0x1be/0x320
[  158.837964]  flush_write_bio.isra.41+0x2c/0x70
[  158.837964]  btree_write_cache_pages+0x3bb/0x7f0
[  158.837964]  do_writepages+0x5c/0x130
[  158.837964]  __filemap_fdatawrite_range+0x175/0x230
[  158.837964]  btrfs_write_marked_extents+0x2b0/0x2f0
[  158.837964]  btrfs_sync_log+0x1006/0x24f0
[  158.837964]  btrfs_sync_file+0x817/0x9e0
[  158.837964]  do_fsync+0x33/0x60
[  158.837964]  __x64_sys_fsync+0x2a/0x40
[  158.837964]  do_syscall_64+0x8c/0x280
[  158.837964]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  158.837964]
[  158.837964] Freed by task 1257:
[  158.837964]  __kasan_slab_free+0x132/0x180
[  158.837964]  kfree+0x99/0x1c0
[  158.837964]  kfree_skb+0x6f/0x180
[  158.837964]  unix_dgram_sendmsg+0x964/0x1010
[  158.837964]  sock_sendmsg+0xae/0xe0
[  158.837964]  ___sys_sendmsg+0x676/0x890
[  158.837964]  __sys_sendmsg+0xd9/0x170
[  158.837964]  do_syscall_64+0x8c/0x280
[  158.837964]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  158.837964]
[  158.837964] The buggy address belongs to the object at ffff88806b90ac80
[  158.837964]  which belongs to the cache kmalloc-512 of size 512
[  158.837964] The buggy address is located 440 bytes inside of
[  158.837964]  512-byte region [ffff88806b90ac80, ffff88806b90ae80)
[  158.837964] The buggy address belongs to the page:
[  158.837964] page:ffffea0001ae4280 count:1 mapcount:0 mapping:ffff88806cc01280 index:0x0 compound_mapcount: 0
[  158.837964] flags: 0x100000000010200(slab|head)
[  158.837964] raw: 0100000000010200 dead000000000100 dead000000000200 ffff88806cc01280
[  158.837964] raw: 0000000000000000 00000000800c000c 00000001ffffffff 0000000000000000
[  158.837964] page dumped because: kasan: bad access detected
[  158.837964]
[  158.837964] Memory state around the buggy address:
[  158.837964]  ffff88806b90ad00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  158.837964]  ffff88806b90ad80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  158.837964] >ffff88806b90ae00: 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc
[  158.837964]                                         ^
[  158.837964]  ffff88806b90ae80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  158.837964]  ffff88806b90af00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  158.837964] ==================================================================
[  158.837964] Disabling lock debugging due to kernel taint

Conclusion

mounting crafted image can cause slab-out-of-bound write in index_rbio_pages function.

It can be used as malicious way.

Discoverer

Team bobfuzzer

Acknowledgments

This Project used ported version(to 5.0.21 and 5.3.14 linux kernel) of filesystem fuzzer 'JANUS' which developed by GeorgiaTech Systems Software & Security Lab(SSLab)

Thank you for the excellent fuzzer and paper below.