Skip to content

Invalid safety assumption in SdtHeaderIterator #245

Open
@usadson

Description

@usadson

The SdtHeaderIterator can be used to iterate over every SdtHeader, but the iterator only maps the size of the SdtHeader (36 bytes), whilst the validation requires that the whole header is mapped (for SSDTs this can be quite large, spanning over multiple pages).

This can be seen in acpi/src/lib.rs:503:

impl<H> Iterator for SdtHeaderIterator<'_, H>
where
    H: AcpiHandler,
{
    type Item = SdtHeader;

    fn next(&mut self) -> Option<Self::Item> {
        // ...

        // SAFETY: `address` needs to be valid for the size of `SdtHeader`, or the ACPI tables are malformed (not a
        // software issue).
        let header_mapping = unsafe {
            self.handler.map_physical_region::<SdtHeader>(table_phys_ptr as usize, mem::size_of::<SdtHeader>())
        };
        let r = header_mapping.validate(header_mapping.signature);

        // ...
    }
}

The last line calls SdtHeader::validate()

pub fn validate(&self, signature: Signature) -> AcpiResult<()> {
    self.validate_header_fields(signature)?;
    self.validate_checksum(signature)?;

    Ok(())
}

Which in turn calls SdtHeader::validate_checksum():

fn validate_checksum(&self, signature: Signature) -> AcpiResult<()> {
        // SAFETY: Entire table is mapped.
        let table_bytes =
            unsafe { core::slice::from_raw_parts((self as *const SdtHeader).cast::<u8>(), self.length as usize) };
        // ...
}

The SAFETY-assumption is that the entire table is mapped, whilst only the header was mapped.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions