summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorTony Dinh <[email protected]>2025-05-28 12:48:39 -0700
committerTom Rini <[email protected]>2025-06-12 13:22:26 -0600
commit53cc4332b3b37218a7cdab8bdb953da57eec2668 (patch)
tree68e6530e5d1e7b13da00e0fe5f78004c7ef519ca /fs
parent52c0290526ce58d55099deb4a1a52bac40a3b0a0 (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.c12
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) {