Skip to content

Latest commit

 

History

History

CVE-2019-19319

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

CVE-2019-19319

Target

Linux Kernel Ext4 FileSystem

Linux Version Availablity
5.0.21 True
5.3.11 False
5.4.0 mount fail

Bug Type

slab-out-of-bounds

Abstract

setxattr operation(after mount crafted image) can cause slab-out-of-bound write vulnerability

Reproduce

gcc -o poc poc_2019_19319.c
mkdir mnt
mount poc_2019_19319.img ./mnt
cp poc ./mnt/
cd mnt
./poc

Details

Debug View

─────────────────────────────────────────────────────────── registers ────
$rax   : 0xffff8880684ebbdc  →  0x68026258ffff8880  →  0x68026258ffff8880
$rbx   : 0xffff8880674ebbd8  →  0x74737973565dbd3e  →  0x74737973565dbd3e
$rcx   : 0xffffffff81a28fa8  →  0x48f6311824548b48  →  0x48f6311824548b48
$rdx   : 0x0000000001000004  →  0x0000000001000004
$rsp   : 0xffff88806a25f0a8  →  0xffff88806a25f250  →  0x0000000000000000 →  0x0000000000000000
$rbp   : 0xffff88806a25f6b8  →  0xffff8880674eb820  →  0x0000000003d80108 →  0x0000000003d80108
$rsi   : 0x0000000000000000  →  0x0000000000000000
$rdi   : 0xffff8880674ebbd8  →  0x74737973565dbd3e  →  0x74737973565dbd3e
$rip   : 0xffffffff81a28fb2  →  0x448b48ffc3fcd9e8  →  0x448b48ffc3fcd9e8
$r8    : 0x0000000000000001  →  0x0000000000000001
$r9    : 0x0000000000000000  →  0x0000000000000000
$r10   : 0x0000000000000000  →  0x0000000000000000
$r11   : 0x0000000000000000  →  0x0000000000000000
$r12   : 0x00000000000003d8  →  0x00000000000003d8
$r13   : 0xdffffc0000000000  →  0xdffffc0000000000
$r14   : 0xffff88806a25f800  →  0xffff88806a25fbdd  →  0x584d394e64685964 →  0x584d394e64685964
$r15   : 0xffff8880674eb820  →  0x0000000003d80108  →  0x0000000003d80108
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflowresume virtualx86 identification]
$cs: 0x0010 $ss: 0x0018 $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
─────────────────────────────────────────────────────────────── stack ────
0xffff88806a25f0a8│+0x0000: 0xffff88806a25f250  →  0x0000000000000000  →0x0000000000000000	 ← $rsp
0xffff88806a25f0b0│+0x0008: 0xffff88806a25f210  →  0x0000000000000000  →0x0000000000000000
0xffff88806a25f0b8│+0x0010: 0xffffffff00000000  →  0xffffffff00000000
0xffff88806a25f0c0│+0x0018: 0x0000000001000004  →  0x0000000001000004
0xffff88806a25f0c8│+0x0020: 0x0000000000000040  →  0x0000000000000040
0xffff88806a25f0d0│+0x0028: 0xffff8880663b03d8  →  0xffff8880663b03d0  →0xffff8880663b03d0  →  [loop detected]
0xffff88806a25f0d8│+0x0030: 0x1ffff1100d44be36  →  0x1ffff1100d44be36
0xffff88806a25f0e0│+0x0038: 0x0000000141b58ab3  →  0x0000000141b58ab3
───────────────────────────────────────────────────────── code:x86:64 ────
   0xffffffff81a28fa8 <ext4_xattr_set_entry+7000> mov    rdx, QWORD PTR [rsp+0x18]
   0xffffffff81a28fad <ext4_xattr_set_entry+7005> xor    esi, esi
   0xffffffff81a28faf <ext4_xattr_set_entry+7007> mov    rdi, rbx
 → 0xffffffff81a28fb2 <ext4_xattr_set_entry+7010> call   0xffffffff81668c90 <memset>
   ↳  0xffffffff81668c90 <memset+0>       push   r12
      0xffffffff81668c92 <memset+2>       push   rbp
      0xffffffff81668c93 <memset+3>       mov    rbp, rdx
      0xffffffff81668c96 <memset+6>       push   rbx
      0xffffffff81668c97 <memset+7>       mov    rcx, QWORD PTR [rsp+0x18]
      0xffffffff81668c9c <memset+12>      mov    rbx, rdi
─────────────────────────────────────────────────────────── arguments ────
memset (
   QWORD var_0 = 0xffff8880674ebbd8 → 0x74737973565dbd3e → 0x74737973565dbd3e,
   int var_1 = 0x0000000000000000 → 0x0000000000000000,
   size_t var_2 = 0x0000000001000004 → 0x0000000001000004
)
───────────────────────────────────────── source:fs/ext4/xattr.c+1706 ────
   1701	 		void *first_val = s->base + min_offs;
   1702	 		size_t offs = le16_to_cpu(here->e_value_offs);
   1703	 		void *val = s->base + offs;
   1704
   1705	 		memmove(first_val + old_size, first_val, val - first_val);
 → 1706	 		memset(first_val, 0, old_size);
   1707	 		min_offs += old_size;
   1708
   1709	 		/* Adjust all value offsets. */
   1710	 		last = s->first;
   1711	 		while (!IS_LAST_ENTRY(last)) {
───────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "", stopped, reason: BREAKPOINT
[#1] Id 2, Name: "", stopped, reason: BREAKPOINT
─────────────────────────────────────────────────────────────── trace ────
[#0] 0xffffffff81a28fb2 → ext4_xattr_set_entry(i=0xffff88806a25f800, s=0xffff88806a25f6b8, handle=<optimized out>, inode=<optimized out>, is_block=<optimized out>)
[#1] 0xffffffff81a2b42a → ext4_xattr_block_set(handle=<optimized out>, inode=<optimized out>, i=0xffff88806a25f800, bs=<optimized out>)
[#2] 0xffffffff81a3268f → ext4_xattr_set_handle(handle=<optimized out>, inode=0xffff8880663bea90, name_index=<optimized out>, name=<optimized out>,value=<optimized out>, value_len=<optimized out>, flags=<optimized out>)
[#3] 0xffffffff81a333e9 → ext4_xattr_set(inode=0xffff8880674ebbd8, name_index=<optimized out>, name=<optimized out>, value=<optimized out>, value_len=<optimized out>, flags=<optimized out>)
[#4] 0xffffffff8172502f → __vfs_setxattr(dentry=0xffff8880662bc500, inode=0xffff8880663bea90, name=0xffff88806a25fbdd "dYhdN9MX", value=0xffff88806c4f4180, size=0x3f, flags=0x2)
[#5] 0xffffffff81727761 → __vfs_setxattr_noperm(dentry=0xffff8880674ebbd8, name=0x0 <irq_stack_union>, value=<optimized out>, size=<optimized out>,flags=0x1)
[#6] 0xffffffff81727aad → vfs_setxattr(dentry=0xffff8880662bc500, name=0xffff88806a25fbd8 "user.dYhdN9MX", value=0xffff88806c4f4180, size=0x3f, flags=0x2)
[#7] 0xffffffff81727d13 → setxattr(d=0xffff8880662bc500, name=<optimized out>, value=<optimized out>, size=0x3f, flags=0x2)
[#8] 0xffffffff81727f36 → path_setxattr(pathname=0x7ffc27602615 "foo/z5NkeKcl", name=<optimized out>, value=<optimized out>, size=<optimized out>, flags=<optimized out>, lookup_flags=0x1)
[#9] 0xffffffff8172803b → __do_sys_setxattr(flags=<optimized out>, size=<optimized out>, value=<optimized out>, name=<optimized out>, pathname=<optimized out>)
──────────────────────────────────────────────────────────────────────────

Thread 2 hit Breakpoint 1, 0xffffffff81a28fb2 in ext4_xattr_set_entry (i=0xffff88806a25f800, s=0xffff88806a25f6b8, handle=<optimized out>, inode=<optimized out>, is_block=<optimized out>) at fs/ext4/xattr.c:1706
1706			memset(first_val, 0, old_size);
gef➤

local variable old_size appears 0x1000004

Bug Causes

fs/ext4/xattr.c:1706 (link)

static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
				struct ext4_xattr_search *s,
				handle_t *handle, struct inode *inode,
				bool is_block)
{
	struct ext4_xattr_entry *last, *next;
	struct ext4_xattr_entry *here = s->here;
	size_t min_offs = s->end - s->base, name_len = strlen(i->name);
	int in_inode = i->in_inode;
	struct inode *old_ea_inode = NULL;
	struct inode *new_ea_inode = NULL;
	size_t old_size, new_size;
	int ret;

	/* Space used by old and new values. */
	old_size = (!s->not_found && !here->e_value_inum) ?
[1]			EXT4_XATTR_SIZE(le32_to_cpu(here->e_value_size)) : 0;
	new_size = (i->value && !in_inode) ? EXT4_XATTR_SIZE(i->value_len) : 0;

	/*
	 * Optimization for the simple case when old and new values have the
	 * same padded sizes. Not applicable if external inodes are involved.
	 */
	if (new_size && new_size == old_size) {
		size_t offs = le16_to_cpu(here->e_value_offs);
		void *val = s->base + offs;

		here->e_value_size = cpu_to_le32(i->value_len);
		if (i->value == EXT4_ZERO_XATTR_VALUE) {
			memset(val, 0, new_size);
		} else {
			memcpy(val, i->value, i->value_len);
			/* Clear padding bytes. */
			memset(val + i->value_len, 0, new_size - i->value_len);
		}
		goto update_hash;
	}

	/* Compute min_offs and last. */
	last = s->first;
	for (; !IS_LAST_ENTRY(last); last = next) {
		next = EXT4_XATTR_NEXT(last);
		if ((void *)next >= s->end) {
			EXT4_ERROR_INODE(inode, "corrupted xattr entries");
			ret = -EFSCORRUPTED;
			goto out;
		}
		if (!last->e_value_inum && last->e_value_size) {
			size_t offs = le16_to_cpu(last->e_value_offs);
			if (offs < min_offs)
				min_offs = offs;
		}
	}

	/* Check whether we have enough space. */
	if (i->value) {
		size_t free;

		free = min_offs - ((void *)last - s->base) - sizeof(__u32);
		if (!s->not_found)
			free += EXT4_XATTR_LEN(name_len) + old_size;

		if (free < EXT4_XATTR_LEN(name_len) + new_size) {
			ret = -ENOSPC;
			goto out;
		}

		/*
		 * If storing the value in an external inode is an option,
		 * reserve space for xattr entries/names in the external
		 * attribute block so that a long value does not occupy the
		 * whole space and prevent futher entries being added.
		 */
		if (ext4_has_feature_ea_inode(inode->i_sb) &&
		    new_size && is_block &&
		    (min_offs + old_size - new_size) <
					EXT4_XATTR_BLOCK_RESERVE(inode)) {
			ret = -ENOSPC;
			goto out;
		}
	}

	/*
	 * Getting access to old and new ea inodes is subject to failures.
	 * Finish that work before doing any modifications to the xattr data.
	 */
	if (!s->not_found && here->e_value_inum) {
		ret = ext4_xattr_inode_iget(inode,
					    le32_to_cpu(here->e_value_inum),
					    le32_to_cpu(here->e_hash),
					    &old_ea_inode);
		if (ret) {
			old_ea_inode = NULL;
			goto out;
		}
	}
	if (i->value && in_inode) {
		WARN_ON_ONCE(!i->value_len);

		ret = ext4_xattr_inode_alloc_quota(inode, i->value_len);
		if (ret)
			goto out;

		ret = ext4_xattr_inode_lookup_create(handle, inode, i->value,
						     i->value_len,
						     &new_ea_inode);
		if (ret) {
			new_ea_inode = NULL;
			ext4_xattr_inode_free_quota(inode, NULL, i->value_len);
			goto out;
		}
	}

	if (old_ea_inode) {
		/* We are ready to release ref count on the old_ea_inode. */
		ret = ext4_xattr_inode_dec_ref(handle, old_ea_inode);
		if (ret) {
			/* Release newly required ref count on new_ea_inode. */
			if (new_ea_inode) {
				int err;

				err = ext4_xattr_inode_dec_ref(handle,
							       new_ea_inode);
				if (err)
					ext4_warning_inode(new_ea_inode,
						  "dec ref new_ea_inode err=%d",
						  err);
				ext4_xattr_inode_free_quota(inode, new_ea_inode,
							    i->value_len);
			}
			goto out;
		}

		ext4_xattr_inode_free_quota(inode, old_ea_inode,
					    le32_to_cpu(here->e_value_size));
	}

	/* No failures allowed past this point. */

	if (!s->not_found && here->e_value_size && !here->e_value_inum) {
		/* Remove the old value. */
		void *first_val = s->base + min_offs;
		size_t offs = le16_to_cpu(here->e_value_offs);
		void *val = s->base + offs;

		memmove(first_val + old_size, first_val, val - first_val);
[2]		memset(first_val, 0, old_size);
		min_offs += old_size;
    ...

in [1], set old_size to huge value, and call memset with old_size

KASAN logs

[  610.867441] EXT4-fs (loop0): mounted filesystem with ordered data mode. Opts: (null)
[  611.627638] cp (1969) used greatest stack depth: 47912 bytes left
[  611.826655] ==================================================================
[  611.827411] BUG: KASAN: use-after-free in ext4_xattr_set_entry+0x1b67/0x3550
[  611.827411] Write of size 16777220 at addr ffff888069becbd8 by task poc/1971
[  611.827411]
[  611.827411] CPU: 1 PID: 1971 Comm: poc Not tainted 5.0.21 #1
[  611.827411] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[  611.827411] Call Trace:
[  611.827411]  dump_stack+0xae/0x14b
[  611.827411]  ? show_regs_print_info+0x5/0x5
[  611.827411]  ? kmsg_dump_rewind_nolock+0xd4/0xd4
[  611.827411]  ? _raw_spin_lock_irqsave+0x9f/0x130
[  611.827411]  ? _raw_write_lock_irqsave+0x130/0x130
[  611.827411]  ? ext4_xattr_set_entry+0x1b67/0x3550
[  611.827411]  print_address_description+0x6e/0x280
[  611.827411]  ? ext4_xattr_set_entry+0x1b67/0x3550
[  611.827411]  ? ext4_xattr_set_entry+0x1b67/0x3550
[  611.827411]  kasan_report+0x149/0x18d
[  611.827411]  ? ext4_xattr_block_set+0x7e1/0x3a00
[  611.827411]  ? ext4_xattr_set_entry+0x1b67/0x3550
[  611.827411]  memset+0x1f/0x40
[  611.827411]  ext4_xattr_set_entry+0x1b67/0x3550
[  611.827411]  ? rcu_is_watching+0x7d/0x130
[  611.827411]  ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  611.827411]  ? rcu_barrier_trace+0x260/0x260
[  611.827411]  ? add_transaction_credits+0x1c7/0xd50
[  611.827411]  ? ext4_xattr_inode_get+0x8e0/0x8e0
[  611.827411]  ? __kernel_text_address+0x9/0x30
[  611.827411]  ? _raw_spin_lock+0x99/0x130
[  611.827411]  ? __kasan_slab_free+0x143/0x180
[  611.827411]  ? kmem_cache_free+0x70/0x1a0
[  611.827411]  ? mb_cache_entry_delete+0x4f3/0x820
[  611.827411]  ? __mb_cache_entry_free+0x10/0x10
[  611.827411]  ? __find_get_block+0x1a3/0xaf0
[  611.827411]  ? __find_get_block+0x1a3/0xaf0
[  611.827411]  ? __find_get_block+0x1a3/0xaf0
[  611.827411]  ? __jbd2_journal_temp_unlink_buffer+0x530/0x530
[  611.827411]  ? try_to_free_buffers+0x4d0/0x4d0
[  611.827411]  ? rcu_qs+0x2f0/0x2f0
[  611.827411]  ? jbd2_journal_get_write_access+0x3d/0x80
[  611.827411]  ext4_xattr_block_set+0x80a/0x3a00
[  611.827411]  ? __getblk_gfp+0xb0/0x8b0
[  611.827411]  ? _cond_resched+0x12/0x60
[  611.827411]  ? __getblk_gfp+0xb0/0x8b0
[  611.827411]  ? ext4_xattr_ibody_set+0x280/0x280
[  611.827411]  ? __find_get_block+0xaf0/0xaf0
[  611.827411]  ? save_stack+0x89/0xb0
[  611.827411]  ? kmem_cache_alloc+0xa7/0x170
[  611.827411]  ? jbd2__journal_start+0x192/0x860
[  611.827411]  ? __ext4_journal_start_sb+0x103/0x330
[  611.827411]  ? ext4_xattr_set+0x187/0x330
[  611.827411]  ? __vfs_setxattr+0x7f/0xb0
[  611.827411]  ? __vfs_setxattr_noperm+0xe1/0x370
[  611.827411]  ? vfs_setxattr+0xbd/0xd0
[  611.827411]  ? path_setxattr+0x156/0x1a0
[  611.827411]  ? __x64_sys_setxattr+0xbb/0x150
[  611.827411]  ? do_syscall_64+0x12b/0x440
[  611.827411]  ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  611.827411]  ? __ext4_get_inode_loc+0x368/0xe20
[  611.827411]  ? ext4_sb_bread+0xa9/0x2b0
[  611.827411]  ? xattr_find_entry+0x11b/0x1e0
[  611.827411]  ? ext4_xattr_block_find.isra.22+0x2fc/0x670
[  611.827411]  ext4_xattr_set_handle+0xe5f/0x18a0
[  611.827411]  ? ext4_xattr_ibody_inline_set+0x280/0x280
[  611.827411]  ? kmem_cache_alloc+0xa7/0x170
[  611.827411]  ? jbd2__journal_start+0x350/0x860
[  611.827411]  ? start_this_handle+0x12c0/0x12c0
[  611.827411]  ? ext4_journal_abort_handle.isra.6+0x260/0x260
[  611.827411]  ? ext4_xattr_get_block+0x6e/0x2f0
[  611.827411]  ext4_xattr_set+0x1b9/0x330
[  611.827411]  ? ext4_xattr_set_credits+0x160/0x160
[  611.827411]  ? selinux_secmark_enabled.part.15+0xd0/0xd0
[  611.827411]  __vfs_setxattr+0x7f/0xb0
[  611.827411]  ? down_write+0x5f/0x100
[  611.827411]  __vfs_setxattr_noperm+0xe1/0x370
[  611.827411]  vfs_setxattr+0xbd/0xd0
[  611.827411]  setxattr+0x253/0x320
[  611.827411]  ? vfs_setxattr+0xd0/0xd0
[  611.827411]  ? kmem_cache_free+0x70/0x1a0
[  611.827411]  ? filename_lookup+0x2ce/0x5b0
[  611.827411]  ? filename_parentat+0x770/0x770
[  611.827411]  ? d_move+0xf0/0xf0
[  611.827411]  ? mpi_resize+0x1d0/0x1d0
[  611.827411]  ? __kasan_kmalloc.constprop.4+0xa0/0xd0
[  611.827411]  ? may_umount_tree+0x270/0x270
[  611.827411]  path_setxattr+0x156/0x1a0
[  611.827411]  ? setxattr+0x320/0x320
[  611.827411]  ? do_sys_truncate+0xef/0x110
[  611.827411]  ? vfs_truncate+0x700/0x700
[  611.827411]  __x64_sys_setxattr+0xbb/0x150
[  611.827411]  ? __x64_sys_removexattr+0x50/0x70
[  611.827411]  do_syscall_64+0x12b/0x440
[  611.827411]  ? syscall_return_slowpath+0x2e0/0x2e0
[  611.827411]  ? __do_page_fault+0x970/0x970
[  611.827411]  ? prepare_exit_to_usermode+0x210/0x210
[  611.827411]  ? perf_trace_sys_enter+0x1050/0x1050
[  611.827411]  ? __x64_sys_sigaltstack+0x270/0x270
[  611.827411]  ? __put_user_4+0x1c/0x30
[  611.827411]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  611.827411] RIP: 0033:0x44b7e9
[  611.827411] Code: 00 b8 00 01 00 00 eb e1 e8 e4 19 00 00 0f 1f 40 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 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48
[  611.827411] RSP: 002b:00007fff96b862e8 EFLAGS: 00000286 ORIG_RAX: 00000000000000bc
[  611.827411] RAX: ffffffffffffffda RBX: 0000000000400400 RCX: 000000000044b7e9
[  611.827411] RDX: 00007fff96b866b0 RSI: 00007fff96b86438 RDI: 00007fff96b863e5
[  611.827411] RBP: 00007fff96b8aae0 R08: 0000000000000002 R09: 00007fff96b8ac08
[  611.827411] R10: 000000000000003f R11: 0000000000000286 R12: 0000000000403160
[  611.827411] R13: 0000000000000000 R14: 00000000006ba018 R15: 0000000000000000
[  611.827411]
[  611.827411] The buggy address belongs to the page:
[  611.827411] page:ffffea0001a6fb00 count:2 mapcount:0 mapping:ffff88806a8c45f8 index:0x810
[  611.827411] 0xffffffff844b0f40
[  611.827411] flags: 0x100000000002032(referenced|lru|active|private)
[  611.827411] raw: 0100000000002032 ffffea00018cc108 ffffea00018c8148 ffff88806a8c45f8
[  611.827411] raw: 0000000000000810 ffff88806622cb28 00000002ffffffff 0000000000000000
[  611.827411] page dumped because: kasan: bad access detected
[  611.827411]
[  611.827411] Memory state around the buggy address:
[  611.827411]  ffff888069becf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  611.827411]  ffff888069becf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[  611.827411] >ffff888069bed000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  611.827411]                    ^
[  611.827411]  ffff888069bed080: fb fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc
[  611.827411]  ffff888069bed100: fc fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  611.827411] ==================================================================
[  611.827411] Disabling lock debugging due to kernel taint
[  611.872754] BUG: unable to handle kernel paging request at ffff888069c62000
[  611.872754] #PF error: [PROT] [WRITE]
[  611.872754] PGD 6401067 P4D 6401067 PUD 6404067 PMD 6978f063 PTE 8000000069c62161
[  611.872754] Oops: 0003 [#1] SMP KASAN NOPTI
[  611.872754] CPU: 1 PID: 1971 Comm: poc Tainted: G    B             5.0.21 #1
[  611.872754] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[  611.872754] RIP: 0010:memset_orig+0x46/0xb0
[  611.872754] Code: 75 70 48 89 d1 48 c1 e9 06 74 39 66 0f 1f 84 00 00 00 00 00 48 ff c9 48 89 07 48 89 47 08 48 89 47 10 48 89 47 18 48 89 47 20 <48> 89 47 28 48 89 47 30 48 89 47 38 48 8d 7f 40 75 d8 0f 1f 84 00
[  611.872754] RSP: 0018:ffff88806c78f0a0 EFLAGS: 00000216
[  611.872754] RAX: 0000000000000000 RBX: ffff888069becbd8 RCX: 000000000003e2af
[  611.872754] RDX: 0000000001000004 RSI: 0000000000000000 RDI: ffff888069c61fd8
[  611.872754] RBP: ffff88806c78f6b8 R08: ffffed100da2609b R09: 0000000000000000
[  611.872754] R10: ffff888069becbd8 R11: ffffed100da2609a R12: 00000000000003d8
[  611.872754] R13: dffffc0000000000 R14: ffff88806c78f800 R15: ffff888069bec820
[  611.872754] FS:  00000000006be880(0000) GS:ffff88806d100000(0000) knlGS:0000000000000000
[  611.872754] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  611.872754] CR2: ffff888069c62000 CR3: 00000000677b0000 CR4: 00000000000006e0
[  611.872754] Call Trace:
[  611.872754]  ext4_xattr_set_entry+0x1b67/0x3550
[  611.872754]  ? rcu_is_watching+0x7d/0x130
[  611.872754]  ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  611.872754]  ? rcu_barrier_trace+0x260/0x260
[  611.872754]  ? add_transaction_credits+0x1c7/0xd50
[  611.872754]  ? ext4_xattr_inode_get+0x8e0/0x8e0
[  611.872754]  ? __kernel_text_address+0x9/0x30
[  611.872754]  ? _raw_spin_lock+0x99/0x130
[  611.872754]  ? __kasan_slab_free+0x143/0x180
[  611.872754]  ? kmem_cache_free+0x70/0x1a0
[  611.872754]  ? mb_cache_entry_delete+0x4f3/0x820
[  611.872754]  ? __mb_cache_entry_free+0x10/0x10
[  611.872754]  ? __find_get_block+0x1a3/0xaf0
[  611.872754]  ? __find_get_block+0x1a3/0xaf0
[  611.872754]  ? __find_get_block+0x1a3/0xaf0
[  611.872754]  ? __jbd2_journal_temp_unlink_buffer+0x530/0x530
[  611.872754]  ? try_to_free_buffers+0x4d0/0x4d0
[  611.872754]  ? rcu_qs+0x2f0/0x2f0
[  611.872754]  ? jbd2_journal_get_write_access+0x3d/0x80
[  611.872754]  ext4_xattr_block_set+0x80a/0x3a00
[  611.872754]  ? __getblk_gfp+0xb0/0x8b0
[  611.872754]  ? _cond_resched+0x12/0x60
[  611.872754]  ? __getblk_gfp+0xb0/0x8b0
[  611.872754]  ? ext4_xattr_ibody_set+0x280/0x280
[  611.872754]  ? __find_get_block+0xaf0/0xaf0
[  611.872754]  ? save_stack+0x89/0xb0
[  611.872754]  ? kmem_cache_alloc+0xa7/0x170
[  611.872754]  ? jbd2__journal_start+0x192/0x860
[  611.872754]  ? __ext4_journal_start_sb+0x103/0x330
[  611.872754]  ? ext4_xattr_set+0x187/0x330
[  611.872754]  ? __vfs_setxattr+0x7f/0xb0
[  611.872754]  ? __vfs_setxattr_noperm+0xe1/0x370
[  611.872754]  ? vfs_setxattr+0xbd/0xd0
[  611.872754]  ? path_setxattr+0x156/0x1a0
[  611.872754]  ? __x64_sys_setxattr+0xbb/0x150
[  611.872754]  ? do_syscall_64+0x12b/0x440
[  611.872754]  ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  611.872754]  ? __ext4_get_inode_loc+0x368/0xe20
[  611.872754]  ? ext4_sb_bread+0xa9/0x2b0
[  611.872754]  ? xattr_find_entry+0x11b/0x1e0
[  611.872754]  ? ext4_xattr_block_find.isra.22+0x2fc/0x670
[  611.872754]  ext4_xattr_set_handle+0xe5f/0x18a0
[  611.872754]  ? ext4_xattr_ibody_inline_set+0x280/0x280
[  611.872754]  ? kmem_cache_alloc+0xa7/0x170
[  611.872754]  ? jbd2__journal_start+0x350/0x860
[  611.872754]  ? start_this_handle+0x12c0/0x12c0
[  611.872754]  ? ext4_journal_abort_handle.isra.6+0x260/0x260
[  611.872754]  ? ext4_xattr_get_block+0x6e/0x2f0
[  611.872754]  ext4_xattr_set+0x1b9/0x330
[  611.872754]  ? ext4_xattr_set_credits+0x160/0x160
[  611.872754]  ? selinux_secmark_enabled.part.15+0xd0/0xd0
[  611.872754]  __vfs_setxattr+0x7f/0xb0
[  611.872754]  ? down_write+0x5f/0x100
[  611.872754]  __vfs_setxattr_noperm+0xe1/0x370
[  611.872754]  vfs_setxattr+0xbd/0xd0
[  611.872754]  setxattr+0x253/0x320
[  611.872754]  ? vfs_setxattr+0xd0/0xd0
[  611.872754]  ? kmem_cache_free+0x70/0x1a0
[  611.872754]  ? filename_lookup+0x2ce/0x5b0
[  611.872754]  ? filename_parentat+0x770/0x770
[  611.872754]  ? d_move+0xf0/0xf0
[  611.872754]  ? mpi_resize+0x1d0/0x1d0
[  611.872754]  ? __kasan_kmalloc.constprop.4+0xa0/0xd0
[  611.872754]  ? may_umount_tree+0x270/0x270
[  611.872754]  path_setxattr+0x156/0x1a0
[  611.872754]  ? setxattr+0x320/0x320
[  611.872754]  ? do_sys_truncate+0xef/0x110
[  611.872754]  ? vfs_truncate+0x700/0x700
[  611.872754]  __x64_sys_setxattr+0xbb/0x150
[  611.872754]  ? __x64_sys_removexattr+0x50/0x70
[  611.872754]  do_syscall_64+0x12b/0x440
[  611.872754]  ? syscall_return_slowpath+0x2e0/0x2e0
[  611.872754]  ? __do_page_fault+0x970/0x970
[  611.872754]  ? prepare_exit_to_usermode+0x210/0x210
[  611.872754]  ? perf_trace_sys_enter+0x1050/0x1050
[  611.872754]  ? __x64_sys_sigaltstack+0x270/0x270
[  611.872754]  ? __put_user_4+0x1c/0x30
[  611.872754]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  611.872754] RIP: 0033:0x44b7e9
[  611.872754] Code: 00 b8 00 01 00 00 eb e1 e8 e4 19 00 00 0f 1f 40 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 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48
[  611.872754] RSP: 002b:00007fff96b862e8 EFLAGS: 00000286 ORIG_RAX: 00000000000000bc
[  611.872754] RAX: ffffffffffffffda RBX: 0000000000400400 RCX: 000000000044b7e9
[  611.872754] RDX: 00007fff96b866b0 RSI: 00007fff96b86438 RDI: 00007fff96b863e5
[  611.872754] RBP: 00007fff96b8aae0 R08: 0000000000000002 R09: 00007fff96b8ac08
[  611.872754] R10: 000000000000003f R11: 0000000000000286 R12: 0000000000403160
[  611.872754] R13: 0000000000000000 R14: 00000000006ba018 R15: 0000000000000000
[  611.872754] Modules linked in:
[  611.872754] CR2: ffff888069c62000
[  611.872754] ---[ end trace 1f7f1665adedcbc6 ]---
[  611.872754] RIP: 0010:memset_orig+0x46/0xb0
[  611.872754] Code: 75 70 48 89 d1 48 c1 e9 06 74 39 66 0f 1f 84 00 00 00 00 00 48 ff c9 48 89 07 48 89 47 08 48 89 47 10 48 89 47 18 48 89 47 20 <48> 89 47 28 48 89 47 30 48 89 47 38 48 8d 7f 40 75 d8 0f 1f 84 00
[  611.872754] RSP: 0018:ffff88806c78f0a0 EFLAGS: 00000216
[  611.872754] RAX: 0000000000000000 RBX: ffff888069becbd8 RCX: 000000000003e2af
[  611.872754] RDX: 0000000001000004 RSI: 0000000000000000 RDI: ffff888069c61fd8
[  611.872754] RBP: ffff88806c78f6b8 R08: ffffed100da2609b R09: 0000000000000000
[  611.872754] R10: ffff888069becbd8 R11: ffffed100da2609a R12: 00000000000003d8
[  611.872754] R13: dffffc0000000000 R14: ffff88806c78f800 R15: ffff888069bec820
[  611.872754] FS:  00000000006be880(0000) GS:ffff88806d100000(0000) knlGS:0000000000000000
[  611.872754] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  611.872754] CR2: ffff888069c62000 CR3: 00000000677b0000 CR4: 00000000000006e0
[  611.930088] BUG: Bad rss-counter state mm:000000003787fc2f idx:0 val:297
[  611.931634] BUG: Bad rss-counter state mm:000000003787fc2f idx:1 val:15
[  611.931774] BUG: non-zero pgtables_bytes on freeing mm: 24576
Segmentation fault

Conclusion

some operation after mount crafted ext4 image can handle local variable old_size, it can occur slab-out-of-bounds vulnerability.

it can be lead to rip handling by attacker

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.