block: fix race between set_blocksize and read paths

commit c0e473a0d226479e8e925d5ba93f751d8df628e9 upstream.

With the new large sector size support, it's now the case that
set_blocksize can change i_blksize and the folio order in a manner that
conflicts with a concurrent reader and causes a kernel crash.

Specifically, let's say that udev-worker calls libblkid to detect the
labels on a block device.  The read call can create an order-0 folio to
read the first 4096 bytes from the disk.  But then udev is preempted.

Next, someone tries to mount an 8k-sectorsize filesystem from the same
block device.  The filesystem calls set_blksize, which sets i_blksize to
8192 and the minimum folio order to 1.

Now udev resumes, still holding the order-0 folio it allocated.  It then
tries to schedule a read bio and do_mpage_readahead tries to create
bufferheads for the folio.  Unfortunately, blocks_per_folio == 0 because
the page size is 4096 but the blocksize is 8192 so no bufferheads are
attached and the bh walk never sets bdev.  We then submit the bio with a
NULL block device and crash.

Therefore, truncate the page cache after flushing but before updating
i_blksize.  However, that's not enough -- we also need to lock out file
IO and page faults during the update.  Take both the i_rwsem and the
invalidate_lock in exclusive mode for invalidations, and in shared mode
for read/write operations.

I don't know if this is the correct fix, but xfs/259 found it.

BUG=b/455114918
TEST=presubmit
RELEASE_NOTE=Fixed CVE-2025-38073 in the Linux kernel.

cos-patch: security-moderate
Change-Id: Ib4d5db782a7dbbff9244cc619e86cd3474a826a6
Signed-off-by: Darrick J. Wong <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Reviewed-by: Luis Chamberlain <[email protected]>
Tested-by: Shin'ichiro Kawasaki <[email protected]>
Link: https://lore.kernel.org/r/174543795699.4139148.2086129139322431423.stgit@frogsfrogsfrogs
Signed-off-by: Jens Axboe <[email protected]>
[ use bdev->bd_inode instead ]
Signed-off-by: Mahmoud Adam <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Kernel CVE Triage Automation <[email protected]>
Reviewed-on: https://cos-review.googlesource.com/c/third_party/kernel/+/115881
Reviewed-by: Daniel Velasquez <[email protected]>
Tested-by: Cusky Presubmit Bot <[email protected]>
Reviewed-by: Dom Huh <[email protected]>
4 files changed