-
Notifications
You must be signed in to change notification settings - Fork 66
Add overlap check between MMIO passthrough regions and MMIO intercept handler regions #327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -223,8 +223,30 @@ impl ZoneInner { | |
| mmio.handler = handler; | ||
| mmio.arg = arg; | ||
| } else { | ||
| let new_region = MMIORegion { start, size }; | ||
|
|
||
| // Check for overlap with existing mmio handler regions. | ||
| if let Some(existing) = self | ||
| .mmio | ||
| .iter() | ||
| .find(|cfg| cfg.region.is_overlap_with(&new_region)) | ||
| { | ||
| panic!( | ||
| "New MMIO handler region {:#x?} overlaps with existing handler {:#x?}", | ||
| new_region, existing.region | ||
| ); | ||
| } | ||
|
|
||
| // Check for overlap with passthrough regions in the stage-2 page table. | ||
| if self.gpm.is_range_overlap(start, size) { | ||
| panic!( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This turns a recoverable zone-configuration error into a hypervisor hang. |
||
| "New MMIO handler region {:#x?} overlaps with passthrough region in stage-2 page table", | ||
| new_region | ||
| ); | ||
| } | ||
|
|
||
| self.mmio.push(MMIOConfig { | ||
| region: MMIORegion { start, size }, | ||
| region: new_region, | ||
| handler, | ||
| arg, | ||
| }) | ||
|
|
@@ -253,6 +275,14 @@ impl ZoneInner { | |
| .find(|cfg| cfg.region.contains_region(addr, size)) | ||
| .map(|cfg| (cfg.region, cfg.handler, cfg.arg)) | ||
| } | ||
|
|
||
| /// Check whether `[start, start+size)` overlaps with any registered MMIO handler region. | ||
| pub fn is_mmio_handler_overlap(&self, start: GuestPhysAddr, size: usize) -> bool { | ||
| let region = MMIORegion { start, size }; | ||
| self.mmio | ||
| .iter() | ||
| .any(|cfg| cfg.region.is_overlap_with(®ion)) | ||
| } | ||
| /// If irq_id belongs to this zone | ||
| pub fn irq_in_zone(&self, irq_id: u32) -> bool { | ||
| let idx = (irq_id / 32) as usize; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only protects mappings created by
pt_init(). Stage-2 mappings are also added later throughgpm_mut(); for example, guest PCI BAR writes calltry_insert_quiet()insrc/pci/pci_handler.rswithout consulting the MMIO handler list. A guest can therefore place a non-MSI-X BAR over an intercepted GPA, create a valid Stage-2 mapping, and make the handler unreachable again. Please route all passthrough mapping insertions through aZoneInnerhelper that performs this cross-check, or cover every runtime insertion path. This applies to all four architecture copies of this check.