Re: [PATCH] fat: fix data race in fat_clusters_flush between free_clusters access

From: OGAWA Hirofumi

Date: Sat Feb 28 2026 - 22:40:01 EST


tejas bharambe <tejas.bharambe@xxxxxxxxxxx> writes:

> From b1b914bdde5bc450eb586141823ba34924606b49 Mon Sep 17 00:00:00 2001
> From: Tejas Bharambe <tejas.bharambe@xxxxxxxxxxx>
> Date: Sat, 28 Feb 2026 09:58:20 -0800
> Subject: [PATCH] fat: fix data race in fat_clusters_flush between
> free_clusters access
>
> fat_clusters_flush() reads sbi->free_clusters and sbi->prev_free
> without holding sbi->fat_lock, while fat_alloc_clusters() modifies
> these fields under the lock. This causes a data race detected by KCSAN.
>
> Fix this by acquiring sbi->fat_lock around the read of these fields
> in fat_clusters_flush().
>
> Reported-by: syzbot+56be2a55de6142438317@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=56be2a55de6142438317
> Signed-off-by: Tejas Bharambe <tejas.bharambe@xxxxxxxxxxx>

What is the real issue with this race other than KCSAN says?
fat_clusters_flush() is called only after marked as dirty. And it is
dirty only after completed the modification of those fields.

AFAICT, on disk data is fixed until unmount even if there is temporary
corruption. Or can you reproduce the real corruption with this race?

Thanks.

> ---
> fs/fat/misc.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/fs/fat/misc.c b/fs/fat/misc.c
> index b154a51627..7d257a5694 100644
> --- a/fs/fat/misc.c
> +++ b/fs/fat/misc.c
> @@ -89,10 +89,12 @@ int fat_clusters_flush(struct super_block *sb)
> le32_to_cpu(fsinfo->signature2),
> sbi->fsinfo_sector);
> } else {
> + mutex_lock(&sbi->fat_lock);
> if (sbi->free_clusters != -1)
> fsinfo->free_clusters = cpu_to_le32(sbi->free_clusters);
> if (sbi->prev_free != -1)
> fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
> + mutex_unlock(&sbi->fat_lock);
> mark_buffer_dirty(bh);
> }
> brelse(bh);

--
OGAWA Hirofumi <hirofumi@xxxxxxxxxxxxxxxxxx>