mirror of
https://github.com/torvalds/linux
synced 2024-10-15 07:47:34 +00:00
buffer: fix grow_buffers() for block size > PAGE_SIZE
We must not shift by a negative number so work in terms of a byte offset to avoid the awkward shift left-or-right-depending-on-sign option. This means we need to use check_mul_overflow() to ensure that a large block number does not result in a wrap. Link: https://lkml.kernel.org/r/20231109210608.2252323-4-willy@infradead.org Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Nathan Chancellor <nathan@kernel.org> Cc: Hannes Reinecke <hare@suse.de> Cc: Luis Chamberlain <mcgrof@kernel.org> Cc: Pankaj Raghav <p.raghav@samsung.com> Cc: Ryusuke Konishi <konishi.ryusuke@gmail.com> [nathan@kernel.org: add cast in grow_buffers() to avoid a multiplication libcall] Link: https://lkml.kernel.org/r/20231128-avoid-muloti4-grow_buffers-v1-1-bc3d0f0ec483@kernel.org Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
382497ada0
commit
5f3bd90d9b
17
fs/buffer.c
17
fs/buffer.c
|
@ -1085,26 +1085,21 @@ static bool grow_dev_folio(struct block_device *bdev, sector_t block,
|
|||
static bool grow_buffers(struct block_device *bdev, sector_t block,
|
||||
unsigned size, gfp_t gfp)
|
||||
{
|
||||
pgoff_t index;
|
||||
int sizebits;
|
||||
|
||||
sizebits = PAGE_SHIFT - __ffs(size);
|
||||
index = block >> sizebits;
|
||||
loff_t pos;
|
||||
|
||||
/*
|
||||
* Check for a block which wants to lie outside our maximum possible
|
||||
* pagecache index. (this comparison is done using sector_t types).
|
||||
* Check for a block which lies outside our maximum possible
|
||||
* pagecache index.
|
||||
*/
|
||||
if (unlikely(index != block >> sizebits)) {
|
||||
printk(KERN_ERR "%s: requested out-of-range block %llu for "
|
||||
"device %pg\n",
|
||||
if (check_mul_overflow(block, (sector_t)size, &pos) || pos > MAX_LFS_FILESIZE) {
|
||||
printk(KERN_ERR "%s: requested out-of-range block %llu for device %pg\n",
|
||||
__func__, (unsigned long long)block,
|
||||
bdev);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Create a folio with the proper size buffers */
|
||||
return grow_dev_folio(bdev, block, index, size, gfp);
|
||||
return grow_dev_folio(bdev, block, pos / PAGE_SIZE, size, gfp);
|
||||
}
|
||||
|
||||
static struct buffer_head *
|
||||
|
|
Loading…
Reference in a new issue