Re: [PATCH] exfat: fix upcase table validation to require all entries consumed

From: David Timber

Date: Tue Oct 27 2026 - 04:02:38 EST


On 10/25/26 12:26, Reid Downing wrote:
> exfat_load_upcase_table() and exfat_load_default_upcase_table()
> accept the table when index >= 0xFFFF, but a correct table must
> process all 0x10000 entries, leaving index at 0x10000.
>
> a crafted filesystem image can use the compressed skip encoding
> to advance index to exactly 0xFFFF without filling the remaining
> entries. the checksum covers only the on-disk bytes so it can be
> made to match. the kernel accepts the table while the unfilled
> entries silently remain zero, causing incorrect uppercase mappings
> for the affected codepoints and breaking case-insensitive filename
> comparison for non-ascii characters.
>
> fix both checks to require index >= UTBL_COUNT.
>
> Fixes: 370e812b3ec1 ("exfat: add nls operations")
> Signed-off-by: Reid Downing <skibletz@xxxxxxxxx>
> ---
> fs/exfat/nls.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c
> index 055447edc..7afc86ea2 100644
> --- a/fs/exfat/nls.c
> +++ b/fs/exfat/nls.c
> @@ -691,7 +691,7 @@ static int exfat_load_upcase_table(struct super_block *sb,
> brelse(bh);
> }
>
> - if (index >= 0xFFFF && utbl_checksum == chksum)
> + if (index >= UTBL_COUNT && utbl_checksum == chksum)
> return 0;
>
> exfat_err(sb, "failed to load upcase table (idx : 0x%08x, chksum : 0x%08x, utbl_chksum : 0x%08x)",
> @@ -728,7 +728,7 @@ static int exfat_load_default_upcase_table(struct super_block *sb)
> }
> }
>
> - if (index >= 0xFFFF)
> + if (index >= UTBL_COUNT)
> return 0;
>
> /* FATAL error: default upcase table has error */
Please see the following unmerged patch:

https://lore.kernel.org/linux-fsdevel/20260414055643.1833401-5-dxdt@xxxxxxxxxxxx/

How about

    index == UTBL_COUNT

This is more of a compatibility issue than a security issue. A bit rot
in the storage hardware can definitely cause benign corruption. I've
observed that EXFAT.sys(the Windows implementation) strictly expects the
table to end exactly with 0x1000.

Also, expect the size of the table aligned to 2 bytes, as per my
original patch. You're more than welcome to cc me in the commit message.
I was just too busy to get back working on my patches.

Thanks,
Davo