From: Jan Kara <j...@suse.cz>

[ Upstream commit 10f04d40a9fa29785206c619f80d8beedb778837 ]

The on-disk quota format supports quota files with upto 2^32 blocks. Be
careful when computing quota file offsets in the quota files from block
numbers as they can overflow 32-bit types. Since quota files larger than
4GB would require ~26 millions of quota users, this is mostly a
theoretical concern now but better be careful, fuzzers would find the
problem sooner or later anyway...

Reviewed-by: Andreas Dilger <adil...@dilger.ca>
Signed-off-by: Jan Kara <j...@suse.cz>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 fs/quota/quota_tree.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c
index bb3f59bcfcf5b..656f9ff63edda 100644
--- a/fs/quota/quota_tree.c
+++ b/fs/quota/quota_tree.c
@@ -61,7 +61,7 @@ static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint 
blk, char *buf)
 
        memset(buf, 0, info->dqi_usable_bs);
        return sb->s_op->quota_read(sb, info->dqi_type, buf,
-              info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
+              info->dqi_usable_bs, (loff_t)blk << info->dqi_blocksize_bits);
 }
 
 static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
@@ -70,7 +70,7 @@ static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint 
blk, char *buf)
        ssize_t ret;
 
        ret = sb->s_op->quota_write(sb, info->dqi_type, buf,
-              info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
+              info->dqi_usable_bs, (loff_t)blk << info->dqi_blocksize_bits);
        if (ret != info->dqi_usable_bs) {
                quota_error(sb, "dquota write failed");
                if (ret >= 0)
@@ -283,7 +283,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
                            blk);
                goto out_buf;
        }
-       dquot->dq_off = (blk << info->dqi_blocksize_bits) +
+       dquot->dq_off = ((loff_t)blk << info->dqi_blocksize_bits) +
                        sizeof(struct qt_disk_dqdbheader) +
                        i * info->dqi_entry_size;
        kfree(buf);
@@ -558,7 +558,7 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo 
*info,
                ret = -EIO;
                goto out_buf;
        } else {
-               ret = (blk << info->dqi_blocksize_bits) + sizeof(struct
+               ret = ((loff_t)blk << info->dqi_blocksize_bits) + sizeof(struct
                  qt_disk_dqdbheader) + i * info->dqi_entry_size;
        }
 out_buf:
-- 
2.27.0



Reply via email to