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
| Impact | Details |
|---|---|
| Access Control | Scope: Access Control Bypass Protection Mechanism - DMA devices possess direct main memory write access. Timing of the attack allows bypassing OS and bootloader access controls. |
| Integrity | Scope: 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
Related CWEs
- CWE-696: Incorrect Behavior Order (parent)
- CWE-1196: Security Flow Issues (category member)
- CWE-1263: Improper Physical Access Control (related)
References
- MITRE Corporation. "CWE-1190: DMA Device Enabled Too Early in Boot Phase." https://cwe.mitre.org/data/definitions/1190.html
- Intel VT-d (Virtualization Technology for Directed I/O)
- UEFI Secure Boot and DMA Protection