DMA Device Enabled Too Early in Boot Phase

Description

DMA Device Enabled Too Early in Boot Phase occurs when a product enables a Direct Memory Access (DMA) capable device before the security configuration settings are established, which allows an attacker to extract data from or gain privileges on the product. DMA enables data transfer between computers and connected devices using direct hardware memory access without operating system interaction. When devices with DMA capabilities power up before boot completion—termed "early boot IPs"—they become potential attack vectors. Virtualization-based security mitigations are typically configured during boot, but early-powered devices may circumvent these protections.

Risk

Enabling DMA devices too early has severe security implications. Untrusted early-boot IPs can launch DMA attacks to access protected assets before security mechanisms activate. Attackers can read sensitive data directly from memory. Memory contents can be modified to gain privilege escalation. Boot security mechanisms can be bypassed. Encryption keys and credentials may be extracted. Code integrity checks can be circumvented. Secure boot processes can be undermined. Full system compromise is possible through DMA attacks.

Solution

Utilize an Input/Output Memory Management Unit (IOMMU) from the start of the boot process to orchestrate IO access control. Delay enabling DMA-capable devices until security controls are established. Configure DMA remapping before enabling devices. Implement boot-time DMA protections. Use Secure Boot with DMA protection extensions. Enable IOMMU/VT-d early in the boot process. Restrict DMA to specific memory regions. Audit which devices have early DMA access. Implement hardware-based memory isolation. Consider devices with built-in DMA restrictions.

Common Consequences

ImpactDetails
Access ControlScope: Access Control

Bypass Protection Mechanism - DMA devices possess direct main memory write access. Timing of the attack allows bypassing OS and bootloader access controls.
IntegrityScope: Integrity

Modify Memory - Attackers can modify memory contents directly through DMA before protections are in place.

Example Code

Vulnerable Code

// Vulnerable: DMA controller enabled before security initialization
// This allows DMA attacks during early boot

module vulnerable_boot_controller (
    input wire clk,
    input wire reset_n,
    input wire power_on,
    output reg dma_enable,
    output reg security_init_done
);

    reg [3:0] boot_stage;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            boot_stage <= 4'b0000;
            dma_enable <= 1'b0;
            security_init_done <= 1'b0;
        end else begin
            case (boot_stage)
                4'b0000: begin
                    // Stage 0: Power on
                    if (power_on) boot_stage <= 4'b0001;
                end

                4'b0001: begin
                    // Stage 1: VULNERABLE - Enable DMA immediately
                    // Security is not yet initialized!
                    dma_enable <= 1'b1;  // DMA enabled too early!
                    boot_stage <= 4'b0010;
                end

                4'b0010: begin
                    // Stage 2: Initialize basic hardware
                    // DMA is already active - attacker can access memory
                    boot_stage <= 4'b0011;
                end

                4'b0011: begin
                    // Stage 3: Initialize security (TOO LATE!)
                    // DMA attacks could have already occurred
                    security_init_done <= 1'b1;
                    boot_stage <= 4'b0100;
                end

                4'b0100: begin
                    // Stage 4: Boot complete
                    // System may already be compromised
                end
            endcase
        end
    end

endmodule

// Vulnerable: No IOMMU protection during early boot
module vulnerable_dma_controller (
    input wire clk,
    input wire dma_request,
    input wire [31:0] src_addr,
    input wire [31:0] dst_addr,
    input wire [15:0] length,
    output reg dma_complete
);

    // DMA controller with no access control
    // Any device can read/write any memory location

    always @(posedge clk) begin
        if (dma_request) begin
            // No address validation
            // No permission checking
            // Direct memory access granted
            perform_dma_transfer(src_addr, dst_addr, length);
            dma_complete <= 1'b1;
        end
    end

endmodule
// Vulnerable: Boot firmware without DMA protection

// Boot sequence that enables DMA too early
void vulnerable_boot_sequence(void) {
    // Stage 1: Basic hardware initialization
    init_clock();
    init_memory_controller();

    // VULNERABLE: Enable PCIe and DMA before security setup
    enable_pcie_bus();
    enable_dma_controllers();  // DMA enabled too early!

    // At this point, malicious DMA devices can:
    // - Read encryption keys from memory
    // - Modify boot code
    // - Bypass secure boot checks

    // Stage 2: Security initialization (TOO LATE)
    init_iommu();  // IOMMU configured after DMA already active
    configure_secure_boot();
    verify_firmware_signature();

    // Stage 3: Continue boot
    load_os_kernel();
}

// Vulnerable: No DMA protection configuration
void enable_dma_controllers(void) {
    // Enable all DMA controllers without restrictions
    for (int i = 0; i < NUM_DMA_CONTROLLERS; i++) {
        dma_controller[i].enabled = true;
        dma_controller[i].access_all_memory = true;  // No restrictions!
        // No IOMMU mapping configured
    }
}

Fixed Code

// Fixed: DMA controller enabled only after security initialization
// IOMMU protection active from start of boot

module secure_boot_controller (
    input wire clk,
    input wire reset_n,
    input wire power_on,
    input wire iommu_ready,
    input wire security_verified,
    output reg dma_enable,
    output reg security_init_done
);

    reg [3:0] boot_stage;

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            boot_stage <= 4'b0000;
            dma_enable <= 1'b0;  // DMA disabled by default
            security_init_done <= 1'b0;
        end else begin
            case (boot_stage)
                4'b0000: begin
                    // Stage 0: Power on - DMA remains disabled
                    if (power_on) boot_stage <= 4'b0001;
                end

                4'b0001: begin
                    // Stage 1: Initialize IOMMU first
                    // DMA still disabled during this phase
                    boot_stage <= 4'b0010;
                end

                4'b0010: begin
                    // Stage 2: Wait for IOMMU to be ready
                    if (iommu_ready) boot_stage <= 4'b0011;
                    // DMA still disabled
                end

                4'b0011: begin
                    // Stage 3: Initialize security settings
                    // Configure memory protection, secure boot
                    boot_stage <= 4'b0100;
                end

                4'b0100: begin
                    // Stage 4: Verify security configuration
                    if (security_verified) begin
                        security_init_done <= 1'b1;
                        boot_stage <= 4'b0101;
                    end
                end

                4'b0101: begin
                    // Stage 5: NOW enable DMA with IOMMU protection
                    // Security is fully initialized
                    dma_enable <= 1'b1;  // Safe to enable now
                    boot_stage <= 4'b0110;
                end

                4'b0110: begin
                    // Stage 6: Boot complete with protection active
                end
            endcase
        end
    end

endmodule

// Fixed: DMA controller with IOMMU integration
module secure_dma_controller (
    input wire clk,
    input wire reset_n,
    input wire dma_request,
    input wire [31:0] src_addr,
    input wire [31:0] dst_addr,
    input wire [15:0] length,
    input wire [7:0] device_id,
    input wire iommu_enabled,
    output reg dma_complete,
    output reg dma_error
);

    // IOMMU lookup signals
    wire iommu_permit;
    wire [31:0] translated_src;
    wire [31:0] translated_dst;

    // IOMMU integration
    iommu_checker iommu (
        .device_id(device_id),
        .src_addr(src_addr),
        .dst_addr(dst_addr),
        .length(length),
        .permit(iommu_permit),
        .translated_src(translated_src),
        .translated_dst(translated_dst)
    );

    always @(posedge clk or negedge reset_n) begin
        if (!reset_n) begin
            dma_complete <= 1'b0;
            dma_error <= 1'b0;
        end else if (dma_request) begin
            // Check IOMMU is enabled
            if (!iommu_enabled) begin
                dma_error <= 1'b1;  // Reject if IOMMU not ready
                dma_complete <= 1'b0;
            end
            // Check IOMMU permission
            else if (!iommu_permit) begin
                dma_error <= 1'b1;  // Access denied by IOMMU
                dma_complete <= 1'b0;
            end
            else begin
                // Use translated addresses from IOMMU
                perform_dma_transfer(translated_src, translated_dst, length);
                dma_complete <= 1'b1;
                dma_error <= 1'b0;
            end
        end
    end

endmodule
// Fixed: Boot firmware with proper DMA protection sequence

void secure_boot_sequence(void) {
    // Stage 1: Basic hardware initialization
    // DMA devices remain disabled
    init_clock();
    init_memory_controller();

    // Stage 2: Initialize IOMMU BEFORE enabling any DMA
    init_iommu();
    configure_iommu_dma_remapping();
    enable_iommu_protection();

    // Stage 3: Configure secure boot
    configure_secure_boot();
    verify_firmware_signature();

    // Stage 4: Set up memory protection
    configure_memory_regions();
    enable_memory_encryption();

    // Stage 5: NOW enable PCIe/DMA with protection active
    enable_pcie_bus_with_iommu();
    enable_dma_controllers_restricted();

    // Stage 6: Continue secure boot
    load_verified_os_kernel();
}

// Fixed: DMA controllers enabled with restrictions
void enable_dma_controllers_restricted(void) {
    // Verify IOMMU is active
    if (!is_iommu_enabled()) {
        panic("Cannot enable DMA without IOMMU protection");
    }

    for (int i = 0; i < NUM_DMA_CONTROLLERS; i++) {
        // Configure IOMMU mapping for each DMA controller
        configure_dma_iommu_mapping(i);

        // Enable with restrictions
        dma_controller[i].enabled = true;
        dma_controller[i].iommu_required = true;
        dma_controller[i].allowed_regions = get_safe_dma_regions();

        // Log enablement for audit
        log_dma_controller_enabled(i);
    }
}

// Fixed: IOMMU initialization
void init_iommu(void) {
    // Enable IOMMU hardware
    iommu_hardware_enable();

    // Set default policy: deny all DMA
    iommu_set_default_policy(IOMMU_DENY_ALL);

    // Configure interrupt remapping
    iommu_configure_interrupt_remapping();

    // Enable DMA remapping
    iommu_enable_dma_remapping();

    // Verify IOMMU is operational
    if (!iommu_verify_operational()) {
        panic("IOMMU initialization failed");
    }
}

CVE Examples

  • CVE-2019-0155: Intel GPU DMA vulnerability allowing privilege escalation
  • DMA attacks via Thunderbolt/FireWire: Multiple CVEs for DMA attacks through external interfaces before protections are established

  • CWE-696: Incorrect Behavior Order (parent)
  • CWE-1196: Security Flow Issues (category member)
  • CWE-1263: Improper Physical Access Control (related)

References

  1. MITRE Corporation. "CWE-1190: DMA Device Enabled Too Early in Boot Phase." https://cwe.mitre.org/data/definitions/1190.html
  2. Intel VT-d (Virtualization Technology for Directed I/O)
  3. UEFI Secure Boot and DMA Protection