vmm: cpu: Reject mis-sized ACPI CPU hotplug register accesses

Reject without asserting that the ACPI CPU hotplug register accesses
match those that are specified by the ACPI definitions.

Signed-off-by: Rob Bradford <rbradford@meta.com>
Assisted-by: Claude:Opus-4.7
This commit is contained in:
Rob Bradford
2026-04-25 22:18:33 +01:00
parent df09e80b89
commit 7ca99204ed

View File

@@ -3226,11 +3226,20 @@ impl BusDevice for AcpiCpuHotplugController {
match offset {
Self::CPU_SELECTION_OFFSET => {
assert!(data.len() >= core::mem::size_of::<u32>());
data[0..core::mem::size_of::<u32>()]
.copy_from_slice(&self.selected_cpu.to_le_bytes());
if data.len() != size_of::<u32>() {
warn!(
"Invalid sized read of CPU selection register: {}",
data.len()
);
return;
}
data.copy_from_slice(&self.selected_cpu.to_le_bytes());
}
Self::CPU_STATUS_OFFSET => {
if data.len() != 1 {
warn!("Invalid sized read of CPU status register: {}", data.len());
return;
}
if self.selected_cpu < self.max_vcpus {
let state = &vcpu_states[usize::try_from(self.selected_cpu).unwrap()];
if state.active() {
@@ -3255,11 +3264,20 @@ impl BusDevice for AcpiCpuHotplugController {
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
match offset {
Self::CPU_SELECTION_OFFSET => {
assert!(data.len() >= core::mem::size_of::<u32>());
self.selected_cpu =
u32::from_le_bytes(data[0..core::mem::size_of::<u32>()].try_into().unwrap());
if data.len() != size_of::<u32>() {
warn!(
"Invalid sized write of CPU selection register: {}",
data.len()
);
return None;
}
self.selected_cpu = u32::from_le_bytes(data.try_into().unwrap());
}
Self::CPU_STATUS_OFFSET => {
if data.len() != 1 {
warn!("Invalid sized write of CPU status register: {}", data.len());
return None;
}
if self.selected_cpu < self.max_vcpus {
// This structure is not shared with the vCPU thread, therefore, holding the
// lock for the entire function doesn't cause any deadlock.