public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
To: Jan Stancek <jstancek@redhat.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] fat: fix corruption in fat_alloc_new_dir()
Date: Sun, 08 Sep 2019 19:20:49 +0900	[thread overview]
Message-ID: <87v9u3xf5q.fsf@mail.parknet.co.jp> (raw)
In-Reply-To: <fc8878aeefea128c105c49671b2a1ac4694e1f48.1567468225.git.jstancek@redhat.com> (Jan Stancek's message of "Tue, 3 Sep 2019 01:59:36 +0200")

Jan Stancek <jstancek@redhat.com> writes:

> sb_getblk does not guarantee that buffer_head is uptodate. If there is
> async read running in parallel for same buffer_head, it can overwrite
> just initialized msdos_dir_entry, leading to corruption:
>   FAT-fs (loop0): error, corrupted directory (invalid entries)
>   FAT-fs (loop0): Filesystem has been set read-only
>
> This can happen for example during LTP statx04, which creates loop
> device, formats it (mkfs.vfat), mounts it and immediately creates
> a new directory. In parallel, systemd-udevd is probing new block
> device, which leads to async read.
>
>   do_mkdirat                      ksys_read
>    vfs_mkdir                       vfs_read
>     vfat_mkdir                      __vfs_read
>      fat_alloc_new_dir               new_sync_read
>        /* init de[0], de[1] */        blkdev_read_iter
>                                        generic_file_read_iter
>                                         generic_file_buffered_read
>                                          blkdev_readpage
>                                           block_read_full_page
>
> Faster reproducer (based on LTP statx04):
>
> int main(void)
> {
> 	int i, j, ret, fd, loop_fd, ctrl_fd;
> 	int loop_num;
> 	char loopdev[256], tmp[256], testfile[256];
>
> 	mkdir("/tmp/mntpoint", 0777);
> 	for (i = 0; ; i++) {
> 		printf("Iteration: %d\n", i);
> 		sprintf(testfile, "/tmp/test.img.%d", getpid());
>
> 		ctrl_fd = open("/dev/loop-control", O_RDWR);
> 		loop_num = ioctl(ctrl_fd, LOOP_CTL_GET_FREE);
> 		close(ctrl_fd);
> 		sprintf(loopdev, "/dev/loop%d", loop_num);
>
> 		fd = open(testfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
> 		fallocate(fd, 0, 0, 256*1024*1024);
> 		close(fd);
>
> 		fd = open(testfile, O_RDWR);
> 		loop_fd = open(loopdev, O_RDWR);
> 		ioctl(loop_fd, LOOP_SET_FD, fd);
> 		close(loop_fd);
> 		close(fd);
>
> 		sprintf(tmp, "mkfs.vfat %s", loopdev);
> 		system(tmp);
> 		mount(loopdev, "/tmp/mntpoint", "vfat", 0, NULL);
>
> 		for (j = 0; j < 200; j++) {
> 			sprintf(tmp, "/tmp/mntpoint/testdir%d", j);
> 			ret = mkdir(tmp, 0777);
> 			if (ret) {
> 				perror("mkdir");
> 				break;
> 			}
> 		}
>
> 		umount("/tmp/mntpoint");
> 		loop_fd = open(loopdev, O_RDWR);
> 		ioctl(loop_fd, LOOP_CLR_FD, fd);
> 		close(loop_fd);
> 		unlink(testfile);
>
> 		if (ret)
> 			break;
> 	}
>
> 	return 0;
> }
>
> Issue triggers within minute on HPE Apollo 70 (arm64, 64GB RAM, 224 CPUs).

Using the device while mounting same device doesn't work reliably like
this race.  (getblk() is intentionally used to get the buffer to write
new data.)

mount(2) internally opens the device by EXCL mode, so I guess udev opens
without EXCL (I dont know if it is intent or not).

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

  reply	other threads:[~2019-09-08 10:20 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-02 23:59 [PATCH] fat: fix corruption in fat_alloc_new_dir() Jan Stancek
2019-09-08 10:20 ` OGAWA Hirofumi [this message]
2019-09-08 19:06   ` Jan Stancek
2019-09-10  3:53     ` OGAWA Hirofumi
2019-09-10 16:27       ` Jan Stancek
2019-09-11  6:55         ` [PATCH] fat: Workaround the race with userspace's read via blockdev while mounting OGAWA Hirofumi

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=87v9u3xf5q.fsf@mail.parknet.co.jp \
    --to=hirofumi@mail.parknet.co.jp \
    --cc=jstancek@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    /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