* KASAN: vmalloc-out-of-bounds Write in vfree_atomic
@ 2026-03-11 8:49 Jianzhou Zhao
2026-03-11 10:48 ` Namjae Jeon
0 siblings, 1 reply; 2+ messages in thread
From: Jianzhou Zhao @ 2026-03-11 8:49 UTC (permalink / raw)
To: urezki, akpm; +Cc: linux-mm, linux-kernel
To: linkinjeon@kernel.org, sj1557.seo@samsung.com
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [BUG] exfat: KASAN: vmalloc-out-of-bounds Write in delayed_free due to double-free of vol_utbl
Dear exFAT Maintainers,
Our custom fuzzing tool, RacePilot, has detected a vmalloc-out-of-bounds write inside the `delayed_free` function. The underlying issue is a double-free vulnerability regarding the upcase table (`vol_utbl`).
### Call Trace:
```
BUG: KASAN: vmalloc-out-of-bounds in llist_add_batch+0x15f/0x180 lib/llist.c:32
Write of size 8 at addr ffffc90005319000 by task syz.4.373/14262
Call Trace:
<IRQ>
...
kasan_report+0x96/0xd0 mm/kasan/report.c:634
llist_add_batch+0x15f/0x180 lib/llist.c:32
llist_add include/linux/llist.h:248 [inline]
vfree_atomic+0x5e/0xe0 mm/vmalloc.c:3326
vfree+0x708/0x8a0 mm/vmalloc.c:3353
delayed_free+0x49/0xb0 fs/exfat/super.c:799
rcu_do_batch kernel/rcu/tree.c:2568 [inline]
...
```
### Underlying Root Cause:
The issue occurs when `exfat_create_upcase_table()` fails to load an upcase table and subsequently fails to load the default fallback due to memory exhaustion (-ENOMEM), causing `sbi->vol_utbl` to be double-freed.
1. During `exfat_create_upcase_table()`, if `exfat_load_upcase_table()` returns an error other than `-EIO` (e.g. `-EINVAL` from a checksum mismatch), the code triggers `exfat_free_upcase_table()` to free the invalid table before jumping to `load_default`.
2. Inside `exfat_free_upcase_table()`, `kvfree(sbi->vol_utbl)` is executed, but `sbi->vol_utbl` is **not set to NULL**.
3. In `load_default:`, the execution calls `exfat_load_default_upcase_table(sb)`.
4. If the system is under memory pressure, `kvcalloc()` inside the default loader fails and returns `-ENOMEM`. Because of this failure, `sbi->vol_utbl` is not overwritten with a new pointer, leaving it holding the previously freed vmalloc address.
5. The `-ENOMEM` failure propagates up, aborting the filesystem mount. The VFS superblock teardown eventually processes to `exfat_kill_sb()`, queuing the RCU callback `delayed_free()`.
6. When `delayed_free()` asynchronously runs, it again calls `exfat_free_upcase_table(sbi)`.
7. `kvfree()` is called for a second time on the old `sbi->vol_utbl`, constituting a double free.
8. Because `delayed_free` executes in a softirq context, `kvfree()` delegates the cleanup to `vfree_atomic()`. `vfree_atomic` casts the virtual address to an `llist_node` and writes its `next` pointer. KASAN catches this illicit write operation on previously freed, unmapped vmalloc memory, emitting the `vmalloc-out-of-bounds` exception.
### Key Code Snippets:
In `fs/exfat/nls.c`, `exfat_create_upcase_table()`:
```c
ret = exfat_load_upcase_table(sb, sector, num_sectors, ...);
brelse(bh);
if (ret && ret != -EIO) {
/* free memory from exfat_load_upcase_table call */
exfat_free_upcase_table(sbi); // [1] Frees ->vol_utbl but leaves a dangling pointer
goto load_default;
}
...
load_default:
/* load default upcase table */
return exfat_load_default_upcase_table(sb); // [2] Fails on kvcalloc and returns -ENOMEM
```
In `fs/exfat/super.c`, inside `delayed_free()`:
```c
static void delayed_free(struct rcu_head *p)
{
...
exfat_free_upcase_table(sbi); // [3] Second invocation leads to double free UAF
exfat_free_sbi(sbi);
}
```
### Proposed Fix:
The solution is natively simple: nullify `sbi->vol_utbl` directly inside `exfat_free_upcase_table()` after freeing it. This safely converts the secondary asynchronous `kvfree` into a no-op.
```c
void exfat_free_upcase_table(struct exfat_sb_info *sbi)
{
kvfree(sbi->vol_utbl);
+ sbi->vol_utbl = NULL;
}
```
Best regards,
The RacePilot Team
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: KASAN: vmalloc-out-of-bounds Write in vfree_atomic
2026-03-11 8:49 KASAN: vmalloc-out-of-bounds Write in vfree_atomic Jianzhou Zhao
@ 2026-03-11 10:48 ` Namjae Jeon
0 siblings, 0 replies; 2+ messages in thread
From: Namjae Jeon @ 2026-03-11 10:48 UTC (permalink / raw)
To: Jianzhou Zhao; +Cc: urezki, akpm, linux-mm, linux-kernel
> ### Proposed Fix:
>
> The solution is natively simple: nullify `sbi->vol_utbl` directly inside `exfat_free_upcase_table()` after freeing it. This safely converts the secondary asynchronous `kvfree` into a no-op.
>
> ```c
> void exfat_free_upcase_table(struct exfat_sb_info *sbi)
> {
> kvfree(sbi->vol_utbl);
> + sbi->vol_utbl = NULL;
> }
> ```
It was already fixed back in early 2025 with commit 1f3d9724e16d
('exfat: fix double free in delayed_free').
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-03-11 10:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 8:49 KASAN: vmalloc-out-of-bounds Write in vfree_atomic Jianzhou Zhao
2026-03-11 10:48 ` Namjae Jeon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox