diff options
| author | Tony Dinh <[email protected]> | 2025-05-28 12:48:39 -0700 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-06-12 13:22:26 -0600 |
| commit | 53cc4332b3b37218a7cdab8bdb953da57eec2668 (patch) | |
| tree | 68e6530e5d1e7b13da00e0fe5f78004c7ef519ca /fs | |
| parent | 52c0290526ce58d55099deb4a1a52bac40a3b0a0 (diff) | |
ext4fs: Fix: Read outside partition error (take 2)
Use lbaint_t for blknr to avoid overflow in ext4fs_read_file().
Background:
blknr (block number) used in ext4fs_read_file() could be increased to a
very large value and causes a wrap around at 32 bit signed integer max,
thus becomes negative. This results in an out-of-normal range for sector
number (during the assignment delayed_start = blknr) where delayed_start
sector is typed uint64 lbaint_t. This causes the "Read outside partition"
error.
Looks like we also have this overflown problem in ext4_write.c that needs
to be addressed.
This patch was tested on the Synology DS116 (Armada 385) board, and a
4TB Seagate HDD.
Signed-off-by: Tony Dinh <[email protected]>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/ext4/ext4fs.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index bd058a09614..9be99594f50 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -102,17 +102,21 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos, blockcnt = lldiv(((len + pos) + blocksize - 1), blocksize); for (i = lldiv(pos, blocksize); i < blockcnt; i++) { - long int blknr; + lbaint_t blknr; + long blknr_and_status; int blockoff = pos - (blocksize * i); int blockend = blocksize; int skipfirst = 0; - blknr = read_allocated_block(&node->inode, i, &cache); - if (blknr < 0) { + blknr_and_status = read_allocated_block(&node->inode, i, &cache); + if (blknr_and_status < 0) { ext_cache_fini(&cache); return -1; } - blknr = blknr << log2_fs_blocksize; + /* Block number could becomes very large when CONFIG_SYS_64BIT_LBA is enabled + * and wrap around at max long int + */ + blknr = (lbaint_t)blknr_and_status << log2_fs_blocksize; /* Last block. */ if (i == blockcnt - 1) { |
