-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AA/attester: support to read CCEL for kernel older than v6.4
linux kernels older than v6.4 does not support to read CCEL from acpi sysfs. This patch supports to read CCEL from dev/mem This is accomplished by reading CCEL's physical address from ACPI table description. Then read the CCEL from /dev/mem. ACPI table to include CCEL patch of linux kernel torvalds/linux@4f855dc Signed-off-by: Xynnn007 <[email protected]>
- Loading branch information
Showing
3 changed files
with
107 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// Copyright (c) 2024 Alibaba Cloud | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
use anyhow::{bail, Context}; | ||
use scroll::Pread; | ||
use tokio::io::{AsyncReadExt, AsyncSeekExt}; | ||
|
||
use crate::tdx::TdxAttester; | ||
|
||
use std::path::Path; | ||
|
||
const CCEL_PATH: &str = "/sys/firmware/acpi/tables/data/CCEL"; | ||
|
||
/// Path to the ACPI table CCEL description | ||
const CCEL_ACPI_DESCRIPTION: &str = "/sys/firmware/acpi/tables/CCEL"; | ||
|
||
/// Guest memory which is used to read the CCEL | ||
const GUEST_MEMORY: &str = "/dev/mem"; | ||
|
||
/// Signature of CCEL's ACPI Description Header | ||
const CCEL_SIGNATURE: &[u8] = b"CCEL"; | ||
|
||
#[repr(C)] | ||
#[derive(Pread)] | ||
struct EfiAcpiDescriptionHeader { | ||
signature: u32, | ||
length: u32, | ||
revision: u8, | ||
checksum: u8, | ||
oem_id: [u8; 6], | ||
oem_table_id: u64, | ||
oem_revision: u32, | ||
craetor_id: u32, | ||
creator_revision: u32, | ||
} | ||
|
||
#[repr(C)] | ||
#[derive(Pread)] | ||
struct TdxEventLogACPITable { | ||
efi_acpi_description_header: EfiAcpiDescriptionHeader, | ||
rsv: u32, | ||
laml: u64, | ||
lasa: u64, | ||
} | ||
|
||
impl TdxAttester { | ||
pub async fn read_ccel() -> anyhow::Result<Vec<u8>> { | ||
if Path::new(CCEL_PATH).exists() { | ||
let ccel = tokio::fs::read(CCEL_PATH).await?; | ||
return Ok(ccel); | ||
} | ||
|
||
let efi_acpi_description = tokio::fs::read(CCEL_ACPI_DESCRIPTION) | ||
.await | ||
.context("read ccel description")?; | ||
let ccel_acpi_table = efi_acpi_description | ||
.pread::<TdxEventLogACPITable>(0) | ||
.context("parse CCEL ACPI description failed")?; | ||
|
||
let ccel_signature = u32::from_le_bytes(CCEL_SIGNATURE.try_into()?); | ||
if ccel_acpi_table.efi_acpi_description_header.signature != ccel_signature { | ||
bail!("invalid CCEL ACPI table: wrong CCEL signature"); | ||
} | ||
|
||
if ccel_acpi_table.rsv != 0 { | ||
bail!("invalid CCEL ACPI table: RSV must be 0"); | ||
} | ||
|
||
if ccel_acpi_table.efi_acpi_description_header.length != efi_acpi_description.len() as u32 { | ||
bail!("invalid CCEL ACPI table: header length not match"); | ||
} | ||
|
||
let mut guest_memory = tokio::fs::OpenOptions::new() | ||
.read(true) | ||
.open(GUEST_MEMORY) | ||
.await?; | ||
guest_memory | ||
.seek(std::io::SeekFrom::Start(ccel_acpi_table.lasa)) | ||
.await?; | ||
let mut ccel = vec![0; ccel_acpi_table.laml as usize]; | ||
let read_size = guest_memory.read(&mut ccel).await?; | ||
if read_size == 0 { | ||
bail!("read CCEL failed"); | ||
} | ||
|
||
Ok(ccel) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::tdx::TdxAttester; | ||
|
||
#[ignore] | ||
#[tokio::test] | ||
async fn test_read_ccel() { | ||
let ccel = TdxAttester::read_ccel().await.unwrap(); | ||
tokio::fs::write("/root/test/guest-components/2.bin", ccel) | ||
.await | ||
.unwrap(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters