The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
To: Igor Putko <igorpetindev@gmail.com>
Cc: linux-kernel@vger.kernel.org,
	syzbot+f72da8b30ddc89cc2371@syzkaller.appspotmail.com
Subject: Re: [PATCH] fat: fix data race in fat_add_entries() over unlocked buffer write
Date: Sun, 16 Aug 2026 21:22:31 +0900	[thread overview]
Message-ID: <87fr0egsqg.fsf@mail.parknet.co.jp> (raw)
In-Reply-To: <20260816105106.3104-1-igorpetindev@gmail.com>

Igor Putko <igorpetindev@gmail.com> writes:

> fat_add_entries() writes new directory entries directly into
> bh->b_data via memcpy() without holding the buffer lock. This is
> inconsistent with every other buffer-filling call site in this file
> (fat_zeroed_cluster(), fat_alloc_new_dir(), fat_add_new_entries())
> and in fs/fat/fatent.c (fat_mirror_bhs()), all of which wrap their
> memcpy()/memset() calls in lock_buffer()/unlock_buffer() specifically
> "to avoid race with userspace read via bdev".
>
> Commit 07bfa4415ab6 ("fat: work around race with userspace's read
> via blockdev while mounting") added that locking to those four call
> sites in 2019, but missed the structurally identical pattern in
> fat_add_entries()'s "Second stage: filling the free entries with new
> entries" block, which writes both the long-name and short-name slots
> into pre-existing (already uptodate) buffer heads the same way.
>
> Since a FAT directory's buffer_head aliases a page in the backing
> block device's page cache, a concurrent write into that page via the
> bdev (e.g. through a loop device backed by shmem, as in the syzbot
> reproducer) races with this unlocked memcpy(), as reported by KCSAN.
>
> Wrap both the long-name and short-name slot writes in
> fat_add_entries() with lock_buffer()/unlock_buffer(), matching the
> pattern used everywhere else in this file.

No. Commit 07bfa4415ab6 prevents the race about the non uptodate
buffer. However, because the your patch is adding the lock to the
uptodate buffer, it will not prevent any *read* side like that commit.

And looks like the syzkaller report would be about the stable page issue
that FAT is not supporting, or just temporary on disk corruption that
fixing later writes.

Thanks.

> Reported-by: syzbot+f72da8b30ddc89cc2371@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=f72da8b30ddc89cc2371
> Fixes: 07bfa4415ab6 ("fat: work around race with userspace's read via blockdev while mounting")
> Signed-off-by: Igor Putko <igorpetindev@gmail.com>
> ---
>  fs/fat/dir.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/fs/fat/dir.c b/fs/fat/dir.c
> index 35bdb6294..c9e2bf472 100644
> --- a/fs/fat/dir.c
> +++ b/fs/fat/dir.c
> @@ -1394,7 +1394,10 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
>  		/* Fill the long name slots. */
>  		for (i = 0; i < long_bhs; i++) {
>  			int copy = umin(sb->s_blocksize - offset, size);
> +			/* Avoid race with userspace read via bdev */
> +			lock_buffer(bhs[i]);
>  			memcpy(bhs[i]->b_data + offset, slots, copy);
> +			unlock_buffer(bhs[i]);
>  			mmb_mark_buffer_dirty(bhs[i],
>  					      &MSDOS_I(dir)->i_metadata_bhs);
>  			offset = 0;
> @@ -1406,7 +1409,10 @@ int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
>  		if (!err && i < nr_bhs) {
>  			/* Fill the short name slot. */
>  			int copy = umin(sb->s_blocksize - offset, size);
> +			/* Avoid race with userspace read via bdev */
> +			lock_buffer(bhs[i]);
>  			memcpy(bhs[i]->b_data + offset, slots, copy);
> +			unlock_buffer(bhs[i]);
>  			mmb_mark_buffer_dirty(bhs[i],
>  					      &MSDOS_I(dir)->i_metadata_bhs);
>  			if (IS_DIRSYNC(dir))

-- 
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

      reply	other threads:[~2026-08-16 12:22 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-16 10:51 [PATCH] fat: fix data race in fat_add_entries() over unlocked buffer write Igor Putko
2026-08-16 12:22 ` OGAWA Hirofumi [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87fr0egsqg.fsf@mail.parknet.co.jp \
    --to=hirofumi@mail.parknet.co.jp \
    --cc=igorpetindev@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=syzbot+f72da8b30ddc89cc2371@syzkaller.appspotmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox