block: vhdx: fix region table overlap detection - #8445
metsw24-max wants to merge 1 commit into
Conversation
|
@weltling could you please take a look? |
weltling
left a comment
There was a problem hiding this comment.
The code fix LGTM. The clippy fix should be trivial.
Thanks
eec7e07 to
9a4fe45
Compare
|
Sorted. The clippy failure was the test's |
sboeuf
left a comment
There was a problem hiding this comment.
Could you please update your commit by including a commit message explaining what the patch is doing?
The title is slightly misleading since the check was already existing, it's more that you're trying to also catch the case where the addition overflow would prevent the overlap to be detected.
| offset += size_of::<RegionTableEntry>(); | ||
| let start = entry.file_offset; | ||
| let end = start + entry.length as u64; | ||
| let end = start.saturating_add(entry.length as u64); |
There was a problem hiding this comment.
I'm not sure that's the right approach here. IIUC, by using saturating_add() you end up always producing a valid u64, which avoids overflowing. This is hiding the fact that the addition didn't go well.
In such case, we should report the error, and that's why using something like checked_add() might help.
There was a problem hiding this comment.
Agreed, saturating just papers over the bad entry. Switched to checked_add so a wrapping start + length now returns a RegionEntryOverflow error instead of being clamped to a valid-looking u64.
FYI: @metsw24-max our commit style can be found here: https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/CONTRIBUTING.md#patch-format--git-commit-hygiene TL;DR: Explain why you change something in a way that is helpful for reviewers |
RegionInfo::new walks the region table and is meant to reject any two entries whose [file_offset, file_offset + length) ranges overlap. Two issues let an overlapping table pass validation. The overlap test was inverted: `!((start >= other_start) || (end <= other_end))` only fires when a new entry fully contains an existing one, so partial and contained overlaps were accepted. Replace it with the usual interval test `start < other_end && end > other_start`. The end offset was also computed with an unchecked `start + length`, which wraps on an entry whose offset and length sum past u64::MAX. A wrapped end yields a bogus range that hides the overlap, so use checked_add and report a RegionEntryOverflow error when it wraps. The offsets come straight from the on-disk table, so a corrupt or crafted image could otherwise present overlapping BAT and metadata regions and still be opened. Add a regression test covering a two-entry table with a partial overlap. Signed-off-by: Sayed Kaif <[email protected]>
9a4fe45 to
4164afb
Compare
|
Reworked the commit in the repo's format with a body that explains the why: the overlap test was inverted so partial overlaps slipped through, and the end offset used an unchecked add that could wrap and mask one. Retitled to "fix region table overlap detection" since, as you noted, the check itself already existed. The overflow path now uses checked_add per the inline note. |
|
@metsw24-max Needs a rebase. |
|
This was already merged as #8483 - but it's probably worth creating a new PR with with |
VHDX region table entries declare a file offset and length, and RegionInfo::new is meant to reject a table whose entries overlap. The check was inverted though:
!((start >= other_start) || (end <= other_end))only fires when a new entry strictly contains an already seen one, so the common case of a partial overlap between two entries passes validation. The offsets come straight from the region table in the image, so a crafted or corrupt VHDX can present overlapping BAT and metadata regions and still be opened.The replacement uses the standard interval test
start < other_end && end > other_start. The end offset was also computed with an uncheckedstart + length, which can wrap on a hostile offset/length near u64::MAX and hide an overlap; it now uses checked_add and reports a RegionEntryOverflow error rather than silently saturating. Behaviour for well formed images is unchanged, and there is a regression test that builds a two entry table with a partial overlap and confirms it is rejected.