Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2926630 authored by Jan Kara's avatar Jan Kara Committed by Greg Kroah-Hartman
Browse files

quota: Don't overflow quota file offsets



[ 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: default avatarAndreas Dilger <adilger@dilger.ca>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 1842dde0
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -62,7 +62,7 @@ static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)


	memset(buf, 0, info->dqi_usable_bs);
	memset(buf, 0, info->dqi_usable_bs);
	return sb->s_op->quota_read(sb, info->dqi_type, buf,
	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)
static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
@@ -71,7 +71,7 @@ static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf)
	ssize_t ret;
	ssize_t ret;


	ret = sb->s_op->quota_write(sb, info->dqi_type, buf,
	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) {
	if (ret != info->dqi_usable_bs) {
		quota_error(sb, "dquota write failed");
		quota_error(sb, "dquota write failed");
		if (ret >= 0)
		if (ret >= 0)
@@ -284,7 +284,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
			    blk);
			    blk);
		goto out_buf;
		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) +
			sizeof(struct qt_disk_dqdbheader) +
			i * info->dqi_entry_size;
			i * info->dqi_entry_size;
	kfree(buf);
	kfree(buf);
@@ -559,7 +559,7 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
		ret = -EIO;
		ret = -EIO;
		goto out_buf;
		goto out_buf;
	} else {
	} 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;
		  qt_disk_dqdbheader) + i * info->dqi_entry_size;
	}
	}
out_buf:
out_buf: