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-19449/
CVE/CVE-2019-19449/

Latest commit

 

Git stats

Files

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

CVE-2019-19449

Target

Linux Kernel 5.0.21 f2fs FileSystem

Bug Type

slab-out-of-bounds read

Abstract

mounting crafted image can cause slab-out-of-bounds read in init_min_max_mtime

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

Reproduce

mkdir mnt
mount poc_2019_19449.img ./mnt

Details

Debug view

───────────────────────────────────────────────────────────────────────────── registers ────
$rax   : 0x001e00007f200000  →  0x001e00007f200000
$rbx   : 0xffff8880685e4e00  →   (bad)
$rcx   : 0xffff88806c7870c0  →  0x0000000000000000  →  0x0000000000000000
$rdx   : 0xdffffc0000000000  →  0xdffffc0000000000
$rsp   : 0xffff8880659df918  →  0x1ffff1100cb3bf38  →  0x1ffff1100cb3bf38
$rbp   : 0x0000000000000019  →  0x0000000000000019
$rsi   : 0xffff88806c786d00  →  0x00000000000300c3  →  0x00000000000300c3
$rdi   : 0xffff88806c7870e0  →  0x0000000000000000  →  0x0000000000000000
$rip   : 0xffffffff81798228  →  0x4c8b48ffb22af3e8  →  0x4c8b48ffb22af3e8
$r8    : 0xffffffff812b9375  →  <__kasan_kmalloc+213> mov DWORD PTR [r12+0x4], eax
$r9    : 0xffffffff81798142  →  0x4800000088bb8d48  →  0x4800000088bb8d48
$r10   : 0xffffffff81798142  →  0x4800000088bb8d48  →  0x4800000088bb8d48
$r11   : 0xffffffff81757e7a  →  0x01e1840fc389c085  →  0x01e1840fc389c085
$r12   : 0x0000000000000401  →  0x0000000000000401
$r13   : 0x0000000000000000  →  0x0000000000000000
$r14   : 0xffff8880668d3380  →   add BYTE PTR [rdi+0x5e], cl
$r15   : 0xffff8880668d3300  →   cmp BYTE PTR [rbx], 0x8d
$eflags: [carry parity adjust zero sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0010 $ss: 0x0018 $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
───────────────────────────────────────────────────────────────────────────────── stack ────
[!] Unmapped address
─────────────────────────────────────────────────────────────────────────── code:x86:64 ────
   0xffffffff8179821b <f2fs_build_segment_manager+12043> lea    rcx, [rsi+rcx*8]
   0xffffffff8179821f <f2fs_build_segment_manager+12047> lea    rdi, [rcx+0x20]
   0xffffffff81798223 <f2fs_build_segment_manager+12051> mov    QWORD PTR [rsp+0x18], rcx
   0xffffffff81798228 <f2fs_build_segment_manager+12056> call   0xffffffff812bad20 <__asan_load8>
   0xffffffff8179822d <f2fs_build_segment_manager+12061> mov    rcx, QWORD PTR [rsp+0x18]
   0xffffffff81798232 <f2fs_build_segment_manager+12066> mov    rax, QWORD PTR [rsp+0x30]
   0xffffffff81798237 <f2fs_build_segment_manager+12071> mov    rsi, QWORD PTR [rsp+0x28]
   0xffffffff8179823c <f2fs_build_segment_manager+12076> add    rax, QWORD PTR [rcx+0x20]
   0xffffffff81798240 <f2fs_build_segment_manager+12080> cmp    ebp, DWORD PTR [rsp+0x8]
───────────────────────────────────────────────────────────────────────────── arguments ────
__asan_load8 (
   long unsigned int var_0 = 0xffff88806c7870e0 → 0x0000000000000000 → 0x0000000000000000
)
───────────────────────────────────────────────────────── source:fs/f2fs/segment.c+4230 ────
   4225	 	for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
   4226	 		unsigned int i;
   4227	 		unsigned long long mtime = 0;
   4228
   4229	 		for (i = 0; i < sbi->segs_per_sec; i++)
 → 4230	 			mtime += get_seg_entry(sbi, segno + i)->mtime;
   4231
   4232	 		mtime = div_u64(mtime, sbi->segs_per_sec);
   4233
   4234	 		if (sit_i->min_mtime > mtime)
   4235	 			sit_i->min_mtime = mtime;
─────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, stopped 0xffffffff81798228 in init_min_max_mtime (), reason: SINGLE STEP
[#1] Id 2, stopped 0xffffffff812df57e in may_lookup (), reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0xffffffff81798228 → init_min_max_mtime(sbi=<optimized out>)
[#1] 0xffffffff81798228 → f2fs_build_segment_manager(sbi=0xffff8880668d3300)
[#2] 0xffffffff81757e7a → f2fs_fill_super(sb=<optimized out>, data=<optimized out>, silent=<optimized out>)
[#3] 0xffffffff812cef1b → mount_bdev(fs_type=<optimized out>, flags=0x0, dev_name=<optimized out>, data=<optimized out>, fill_super=0xffffffff81756200 <f2fs_fill_super>)
[#4] 0xffffffff812cfd1c → mount_fs(type=0xffffffff83224f40 <f2fs_fs_type>, flags=0x0, name=0xffff8880662ff100 "/dev/loop0", data=0x0 <irq_stack_union>)
[#5] 0xffffffff812fd7ff → vfs_kern_mount(type=0xffffffff83224f40 <f2fs_fs_type>, flags=0x0, name=0xffff8880662ff100 "/dev/loop0", data=0x0 <irq_stack_union>)
[#6] 0xffffffff8130218a → do_new_mount(data=<optimized out>, name=<optimized out>, mnt_flags=<optimized out>, sb_flags=<optimized out>, fstype=<optimized out>, path=<optimized out>)
[#7] 0xffffffff8130218a → do_mount(dev_name=0xffff8880662ff100 "/dev/loop0", dir_name=<optimized out>, type_page=<optimized out>, flags=0x0, data_page=0x0 <irq_stack_union>)
[#8] 0xffffffff81303879 → ksys_mount(dev_name=<optimized out>, dir_name=0x55e6e0209f60 "/root/images/mnt", type=<optimized out>, flags=0xc0ed0000, data=<optimized out>)
[#9] 0xffffffff8130391d → __do_sys_mount(data=<optimized out>, flags=<optimized out>, type=<optimized out>, dir_name=<optimized out>, dev_name=<optimized out>)
────────────────────────────────────────────────────────────────────────────────────────────

Bug causes

 static void init_min_max_mtime(struct f2fs_sb_info *sbi)
{
	struct sit_info *sit_i = SIT_I(sbi);
	unsigned int segno;

	down_write(&sit_i->sentry_lock);

	sit_i->min_mtime = ULLONG_MAX;

	for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
		unsigned int i;
		unsigned long long mtime = 0;

		for (i = 0; i < sbi->segs_per_sec; i++)
(1)		  mtime += get_seg_entry(sbi, segno + i)->mtime;

		mtime = div_u64(mtime, sbi->segs_per_sec);

		if (sit_i->min_mtime > mtime)
			sit_i->min_mtime = mtime;
	}
	sit_i->max_mtime = get_mtime(sbi, false);
	up_write(&sit_i->sentry_lock);
}

static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi,
						unsigned int segno)
{
	struct sit_info *sit_i = SIT_I(sbi);
	return &sit_i->sentries[segno];
}

when segno + i greater than 0x19, get_seg_entry returns out-of-bound memory pointer.

KASAN logs

[  208.086266] F2FS-fs (loop0): Fix alignment : done, start(4096) end(436224000) block(12288)
[  208.178227] F2FS-fs (loop0): Fix alignment : done, start(4096) end(16384) block(10752)
[  208.261239] F2FS-fs (loop0): invalid cp_pack_total_block_count:33023
[  208.579490] ==================================================================
[  208.579490] BUG: KASAN: slab-out-of-bounds in f2fs_build_segment_manager+0x2f1d/0x2f80
[  208.579490] Read of size 8 at addr ffff88806c7870e0 by task mount/1833
[  208.579490]
[  208.579490] CPU: 0 PID: 1833 Comm: mount Not tainted 5.0.21 #2
[  208.579490] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[  208.579490] Call Trace:
[  208.579490]  dump_stack+0x5b/0x8b
[  208.579490]  print_address_description+0x70/0x280
[  208.579490]  ? f2fs_build_segment_manager+0x2f1d/0x2f80
[  208.579490]  kasan_report+0x13a/0x19b
[  208.579490]  ? f2fs_build_segment_manager+0x2f1d/0x2f80
[  208.579490]  ? __asan_store4+0x60/0x80
[  208.579490]  ? f2fs_build_segment_manager+0x2f1d/0x2f80
[  208.579490]  f2fs_build_segment_manager+0x2f1d/0x2f80
[  208.579490]  ? f2fs_flush_sit_entries+0x1190/0x1190
[  208.579490]  ? cpumask_next+0x16/0x20
[  208.579490]  f2fs_fill_super+0x1c7a/0x2d50
[  208.579490]  ? f2fs_commit_super+0x2f0/0x2f0
[  208.579490]  ? sb_set_blocksize+0x16/0x70
[  208.579490]  ? set_blocksize+0x83/0x130
[  208.579490]  ? f2fs_commit_super+0x2f0/0x2f0
[  208.579490]  mount_bdev+0x1bb/0x200
[  208.579490]  mount_fs+0xac/0x210
[  208.579490]  ? emergency_thaw_all+0xa0/0xa0
[  208.579490]  ? memcpy+0x34/0x50
[  208.579490]  ? __init_waitqueue_head+0x29/0x30
[  208.579490]  vfs_kern_mount+0x5f/0x190
[  208.579490]  do_mount+0x30a/0x1500
[  208.579490]  ? __schedule+0x5d9/0xb40
[  208.579490]  ? copy_mount_string+0x20/0x20
[  208.579490]  ? __sched_text_start+0x8/0x8
[  208.579490]  ? kasan_unpoison_shadow+0x31/0x40
[  208.579490]  ? __kasan_kmalloc+0xd5/0xf0
[  208.579490]  ? strndup_user+0x3a/0x60
[  208.579490]  ? __kmalloc_track_caller+0xc7/0x1c0
[  208.579490]  ? _copy_from_user+0x61/0x90
[  208.579490]  ? memdup_user+0x39/0x60
[  208.579490]  ksys_mount+0x79/0xc0
[  208.579490]  __x64_sys_mount+0x5d/0x70
[  208.579490]  do_syscall_64+0x5e/0x150
[  208.579490]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  208.579490] RIP: 0033:0x7fd6debe348a
[  208.579490] Code: 48 8b 0d 11 fa 2a 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d de f9 2a 00 f7 d8 64 89 01 48
[  208.579490] RSP: 002b:00007ffd5e0515b8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5
[  208.579490] RAX: ffffffffffffffda RBX: 000055e6e0208080 RCX: 00007fd6debe348a
[  208.579490] RDX: 000055e6e020a760 RSI: 000055e6e0209f60 RDI: 000055e6e020de90
[  208.579490] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000020
[  208.579490] R10: 00000000c0ed0000 R11: 0000000000000206 R12: 000055e6e020de90
[  208.579490] R13: 000055e6e020a760 R14: 0000000000000000 R15: 00000000ffffffff
[  208.579490]
[  208.579490] Allocated by task 1833:
[  208.579490]  __kasan_kmalloc+0xd5/0xf0
[  208.579490]  f2fs_build_segment_manager+0x472/0x2f80
[  208.579490]  f2fs_fill_super+0x1c7a/0x2d50
[  208.579490]  mount_bdev+0x1bb/0x200
[  208.579490]  mount_fs+0xac/0x210
[  208.579490]  vfs_kern_mount+0x5f/0x190
[  208.579490]  do_mount+0x30a/0x1500
[  208.579490]  ksys_mount+0x79/0xc0
[  208.579490]  __x64_sys_mount+0x5d/0x70
[  208.579490]  do_syscall_64+0x5e/0x150
[  208.579490]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  208.579490]
[  208.579490] Freed by task 1243:
[  208.579490]  __kasan_slab_free+0x132/0x180
[  208.579490]  kfree+0x8c/0x1a0
[  208.579490]  consume_skb+0x40/0xd0
[  208.579490]  skb_free_datagram+0xd/0x60
[  208.579490]  unix_dgram_recvmsg+0x5cb/0x810
[  208.579490]  ___sys_recvmsg+0x1bc/0x390
[  208.579490]  __sys_recvmsg+0xd6/0x150
[  208.579490]  do_syscall_64+0x5e/0x150
[  208.579490]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  208.579490]
[  208.579490] The buggy address belongs to the object at ffff88806c786d00
[  208.579490]  which belongs to the cache kmalloc-1k of size 1024
[  208.579490] The buggy address is located 992 bytes inside of
[  208.579490]  1024-byte region [ffff88806c786d00, ffff88806c787100)
[  208.579490] The buggy address belongs to the page:
[  208.579490] page:ffffea0001b1e100 count:1 mapcount:0 mapping:ffff88806d001140 index:0x0 compound_mapcount: 0
[  208.579490] flags: 0x100000000010200(slab|head)
[  208.579490] raw: 0100000000010200 ffffea0001b08e00 0000000300000003 ffff88806d001140
[  208.579490] raw: 0000000000000000 00000000800e000e 00000001ffffffff 0000000000000000
[  208.579490] page dumped because: kasan: bad access detected
[  208.579490]
[  208.579490] Memory state around the buggy address:
[  208.579490]  ffff88806c786f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  208.579490]  ffff88806c787000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  208.579490] >ffff88806c787080: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
[  208.579490]                                                        ^
[  208.579490]  ffff88806c787100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  208.579490]  ffff88806c787180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  208.579490] ==================================================================

Conclusion

Mounting Crafted image can cause slab-out-of-bounds in init_min_max_mtime 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.