[BUG] efs: out-of-bounds in efs_symlink_read_folio+0x1b8/0x440 during readlink()

From: 주형정

Date: Sun Mar 08 2026 - 04:50:14 EST


Hello,

I am reporting a filesystem bug reproduced on current mainline with
KASAN enabled.

Target file: fs/efs/symlink.c
Subsystem: fs/efs
Git head: 5ee8dbf54602dc340d6235b1d6aa17c0f283f48c
Kernel release: 7.0.0-rc2+
Case ID: case-20260307T185409Z-093c

Root cause:
`fs/efs/inode.c` copies the on-disk `efs_dinode.di_size` field into
`inode->i_size`, and `fs/efs/symlink.c` narrows that value back to
signed `efs_block_t` with `efs_block_t size = inode->i_size;`. Because
`efs_block_t` is `int32_t`, any crafted symlink size >= `0x80000000`
becomes negative, bypasses the `size > 2 * EFS_BLOCKSIZE` guard, and
is then used as both a `memcpy()` length and the index for
`link[size]`, causing synchronous out-of-bounds memory access while
filling the symlink folio.

Observed crash: out-of-bounds in efs_symlink_read_folio+0x1b8/0x440
during readlink()

KASAN excerpt:
[ 68.942491][ T1] CPA protect Rodata RO: 0xffffffffac95e000 -
0xffffffffac95efff PFN 1ff5e req 8000000000000123 prevent
0000000000000002
[ 68.942669][ T1] CPA protect Rodata RO: 0xff1100001ff5e000 -
0xff1100001ff5efff PFN 1ff5e req 8000000000000123 prevent
0000000000000002
[ 68.943342][ T1] Testing CPA: again
[ 68.990028][ T1] debug: unmapping init [mem
0xffffffffaa71e000-0xffffffffaa7fffff]
[ 68.991190][ T1] debug: unmapping init [mem
0xffffffffac95f000-0xffffffffac9fffff]
[ 71.381565][ T1] x86/mm: Checked W+X mappings: passed, no W+X pages found.
[ 71.382779][ T1] rodata_test: all tests were successful
[ 71.384395][ T1] Run /init as init process
[kaudit] guest init start
[kaudit] guest init start
+ '[' -x /poc/serial-mark ]
+ /poc/serial-mark '[kaudit] run.sh start\n'
[kaudit] run.sh start\n[ 72.070980][ T143] serial-mark (143) used
greatest stack depth: 8 bytes left
+ echo '[kaudit] trigger command: /poc/poc-bin'
[kaudit] trigger command: /poc/poc-bin
+ /poc/poc-bin
[ 72.382567][ T144] loop0: detected capacity change from 0 to 5
[*] crafted EFS image at /tmp/efs-symlink.img
[*] attached /dev/loop0 and invoking readlink(/mnt/efs/poc)
[ 72.452535][ T144]
==================================================================
[ 72.452929][ T144] BUG: KASAN: out-of-bounds in
efs_symlink_read_folio+0x1b8/0x440
[ 72.453107][ T144] Read of size 18446744073709551615 at addr
ff11000018906800 by task poc-bin/144
[ 72.453251][ T144]
[ 72.453457][ T144] CPU: 0 UID: 0 PID: 144 Comm: poc-bin Tainted: G
W T 7.0.0-rc2+ #14 PREEMPT(lazy)
e3b9bc880e916193e5a1a669fc7b8172bdbeb62e
[ 72.453583][ T144] Tainted: [W]=WARN, [T]=RANDSTRUCT
[ 72.453596][ T144] Hardware name: QEMU Standard PC (i440FX + PIIX,
1996), BIOS 1.15.0-1 04/01/2014
[ 72.453642][ T144] Call Trace:
[ 72.453673][ T144] <TASK>
[ 72.453696][ T144] dump_stack_lvl+0x95/0x100
[ 72.453735][ T144] print_address_description.constprop.0+0x2c/0x3c0
[ 72.453762][ T144] ? efs_symlink_read_folio+0x1b8/0x440
[ 72.453788][ T144] print_report+0xb4/0x280
[ 72.453809][ T144] ? kasan_addr_to_slab+0x27/0x80
[ 72.453824][ T144] ? kasan_complete_mode_report_info+0xa3/0xc0
[ 72.453842][ T144] ? efs_symlink_read_folio+0x1b8/0x440
[ 72.453855][ T144] kasan_report+0xcf/0x140
[ 72.453876][ T144] ? efs_symlink_read_folio+0x1b8/0x440
[ 72.453906][ T144] kasan_check_range+0x3b/0x200
[ 72.453923][ T144] __asan_memcpy+0x24/0x80
[ 72.453942][ T144] efs_symlink_read_folio+0x1b8/0x440
[ 72.453960][ T144] ? __pfx_efs_symlink_read_folio+0x40/0x40
[ 72.453976][ T144] filemap_read_folio+0xba/0x280
[ 72.453999][ T144] ? __pfx_filemap_read_folio+0x40/0x40
[ 72.454014][ T144] ? __filemap_get_folio_mpol+0x55/0x800
[ 72.454042][ T144] do_read_cache_folio+0x1eb/0x500
[ 72.454056][ T144] ? __pfx_efs_symlink_read_folio+0x40/0x40
[ 72.454081][ T144] __page_get_link.isra.0+0x26/0x340
[ 72.454103][ T144] page_get_link+0x40/0x100
[ 72.454121][ T144] vfs_readlink+0x1de/0x400
[ 72.454139][ T144] ? __pfx_vfs_readlink+0x40/0x40
[ 72.454159][ T144] ? touch_atime+0x91/0x640
[ 72.454182][ T144] do_readlinkat+0x1c1/0x300
[ 72.454203][ T144] ? __pfx_do_readlinkat+0x40/0x40
[ 72.454235][ T144] __x64_sys_readlink+0x78/0xc0
[ 72.454251][ T144] do_syscall_64+0x141/0xf40
[ 72.454308][ T144] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 72.454362][ T144] RIP: 0033:0x448d5b
[ 72.454767][ T144] Code: 0c 00 00 00 ba 0c 00 00 00 e9 7e fd ff ff
64 c7 03 22 00 00 00 ba 22 00 00 00 e9 6d fd ff ff f3 0f 1e fa b8 59
00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8
64 89 01 48
[ 72.454792][ T144] RSP: 002b:00007fff8fdb1568 EFLAGS: 00000246
ORIG_RAX: 0000000000000059
[ 72.454834][ T144] RAX: ffffffffffffffda RBX: 00007fff8fdb2798
RCX: 0000000000448d5b
[ 72.454847][ T144] RDX: 0000000000000fff RSI: 00007fff8fdb1570
RDI: 000000000049905e
[ 72.454857][ T144] RBP: 0000000000499004 R08: 00000000004b05fd
R09: 0000000000000000
[ 72.454867][ T144] R10: 0000000000000001 R11: 0000000000000246
R12: 000000000049913c
[ 72.454877][ T144] R13: 0000000000499136 R14: 00000000004c37d0
R15: 0000000000000001
[ 72.454941][ T144] </TASK>
[ 72.454985][ T144]
[ 72.457889][ T144] The buggy address belongs to the physical page:
[ 72.458294][ T144] page: refcount:3 mapcount:0
mapping:ff11000001430a18 index:0x0 pfn:0x18906
[ 72.458491][ T144] memcg:ff11000001c90040
[ 72.458780][ T144] aops:def_blk_aops ino:700000 dentry name(?):""
[ 72.458971][ T144] flags:
0xfffffc6004204(referenced|workingset|private|node=0|zone=1|lastcpupid=0x1fffff)
[ 72.459605][ T144] raw: 000fffffc6004204 0000000000000000
dead000000000122 ff11000001430a18
[ 72.459730][ T144] raw: 0000000000000000 ff11000006a83948
00000003ffffffff ff11000001c90040
[ 72.459901][ T144] page dumped because: kasan: bad access detected
[ 72.460006][ T144]
[ 72.460097][ T144] Memory state around the buggy address:
[ 72.460355][ T144] ff11000018906700: 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00
[ 72.460507][ T144] ff11000018906780: 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00
[ 72.460631][ T144] >ff11000018906800: 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00
[ 72.460747][ T144] ^
[ 72.460930][ T144] ff11000018906880: 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00
[ 72.461032][ T144] ff11000018906900: 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00
[ 72.461174][ T144]
==================================================================
[ 72.461592][ T144] Disabling lock debugging due to kernel taint
[ 72.461796][ T144]
==================================================================
[ 72.462033][ T144] BUG: KASAN: slab-out-of-bounds in
efs_symlink_read_folio+0x309/0x440
[ 72.462162][ T144] Write of size 1 at addr ff11000005f60fff by
task poc-bin/144
[ 72.462261][ T144]
[ 72.462347][ T144] CPU: 0 UID: 0 PID: 144 Comm: poc-bin Tainted: G
B W T 7.0.0-rc2+ #14 PREEMPT(lazy)
e3b9bc880e916193e5a1a669fc7b8172bdbeb62e
[ 72.462391][ T144] Tainted: [B]=BAD_PAGE, [W]=WARN, [T]=RANDSTRUCT
[ 72.462401][ T144] Hardware name: QEMU Standard PC (i440FX + PIIX,
1996), BIOS 1.15.0-1 04/01/2014
[ 72.462415][ T144] Call Trace:
[ 72.462464][ T144] <TASK>
[ 72.462493][ T144] dump_stack_lvl+0x95/0x100
[ 72.462525][ T144] print_address_description.constprop.0+0x2c/0x3c0
[ 72.462553][ T144] ? efs_symlink_read_folio+0x309/0x440
[ 72.462571][ T144] print_report+0xb4/0x280
[ 72.462590][ T144] ? kasan_addr_to_slab+0x27/0x80
[ 72.462606][ T144] ? kasan_complete_mode_report_info+0x32/0xc0
[ 72.462623][ T144] ? efs_symlink_read_folio+0x309/0x440