Skip to content

Commit d0f1d18

Browse files
authored
Set can_trust_host if TDX debug bit is set (#1635)
Release backport of PR #1501 and PR #1627. If the debug bit is set in the VM's TDX attributes, the host can be trusted. This change gets the TD report in the boot shim and checks the debug bit. If it's set, parse the dynamic command line to allow enabling, e.g., confidential debugging. Note that microsoft/OHCL-Linux-Kernel#79 will need to be resolved before hardware debug can be disabled in the manifest.
1 parent 707fe61 commit d0f1d18

File tree

17 files changed

+155
-24
lines changed

17 files changed

+155
-24
lines changed

Cargo.lock

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3399,7 +3399,6 @@ dependencies = [
33993399
"thiserror 2.0.12",
34003400
"tracing",
34013401
"tracing-subscriber",
3402-
"underhill_confidentiality",
34033402
"vbs_defs",
34043403
"x86defs",
34053404
"zerocopy 0.8.24",
@@ -4828,6 +4827,7 @@ dependencies = [
48284827
"sha2",
48294828
"sidecar_defs",
48304829
"tdcall",
4830+
"tdx_guest_device",
48314831
"underhill_confidentiality",
48324832
"x86defs",
48334833
"zerocopy 0.8.24",
@@ -6728,6 +6728,7 @@ version = "0.0.0"
67286728
dependencies = [
67296729
"hvdef",
67306730
"memory_range",
6731+
"tdx_guest_device",
67316732
"thiserror 2.0.12",
67326733
"tracing",
67336734
"x86defs",
@@ -6737,6 +6738,7 @@ dependencies = [
67376738
name = "tdx_guest_device"
67386739
version = "0.0.0"
67396740
dependencies = [
6741+
"bitfield-struct 0.10.1",
67406742
"nix 0.27.1",
67416743
"static_assertions",
67426744
"thiserror 2.0.12",

openhcl/openhcl_attestation_protocol/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ open_enum.workspace = true
1111
guid.workspace = true
1212
mesh.workspace = true
1313
sev_guest_device.workspace = true
14-
tdx_guest_device.workspace = true
14+
tdx_guest_device = { workspace = true, features = ["std"] }
1515

1616
base64.workspace = true
1717
base64-serde.workspace = true

openhcl/openhcl_boot/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ zerocopy.workspace = true
3030
[target.'cfg(target_arch = "x86_64")'.dependencies]
3131
safe_intrinsics.workspace = true
3232
tdcall.workspace = true
33+
tdx_guest_device.workspace = true
3334
x86defs.workspace = true
3435

3536
[build-dependencies]

openhcl/openhcl_boot/src/arch/x86_64/tdx.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use tdcall::Tdcall;
1313
use tdcall::TdcallInput;
1414
use tdcall::TdcallOutput;
1515
use tdcall::tdcall_map_gpa;
16+
use tdx_guest_device::protocol::TdReport;
17+
use x86defs::tdx::TdCallResult;
1618

1719
/// Perform a tdcall instruction with the specified inputs.
1820
fn tdcall(input: TdcallInput) -> TdcallOutput {
@@ -119,3 +121,8 @@ pub fn get_tdx_tsc_reftime() -> Option<u64> {
119121
}
120122
None
121123
}
124+
125+
/// Gets the TdReport.
126+
pub fn get_tdreport(report: &mut TdReport) -> Result<(), TdCallResult> {
127+
tdcall::tdcall_mr_report(&mut TdcallInstruction, report)
128+
}

openhcl/openhcl_boot/src/main.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ fn build_kernel_command_line(
7373
cmdline: &mut ArrayString<COMMAND_LINE_SIZE>,
7474
partition_info: &PartitionInfo,
7575
can_trust_host: bool,
76+
is_confidential_debug: bool,
7677
sidecar: Option<&SidecarConfig<'_>>,
7778
) -> Result<(), CommandLineTooLong> {
7879
// For reference:
@@ -254,6 +255,14 @@ fn build_kernel_command_line(
254255
)?;
255256
}
256257

258+
if is_confidential_debug {
259+
write!(
260+
cmdline,
261+
"{}=1 ",
262+
underhill_confidentiality::OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME
263+
)?;
264+
}
265+
257266
// Only when explicitly supported by Host.
258267
// TODO: Move from command line to device tree when stabilized.
259268
if partition_info.nvme_keepalive && !partition_info.vtl2_pool_memory.is_empty() {
@@ -581,6 +590,29 @@ fn get_ref_time(isolation: IsolationType) -> Option<u64> {
581590
}
582591
}
583592

593+
fn get_hw_debug_bit(isolation: IsolationType) -> bool {
594+
match isolation {
595+
#[cfg(target_arch = "x86_64")]
596+
IsolationType::Tdx => {
597+
use tdx_guest_device::protocol::TdReport;
598+
599+
use crate::arch::tdx::get_tdreport;
600+
601+
let mut report = off_stack!(PageAlign<TdReport>, zeroed());
602+
match get_tdreport(&mut report.0) {
603+
Ok(()) => report.0.td_info.td_info_base.attributes.debug(),
604+
Err(_) => false,
605+
}
606+
}
607+
#[cfg(target_arch = "x86_64")]
608+
IsolationType::Snp => {
609+
// Not implemented yet for SNP.
610+
false
611+
}
612+
_ => false,
613+
}
614+
}
615+
584616
fn shim_main(shim_params_raw_offset: isize) -> ! {
585617
let p = shim_parameters(shim_params_raw_offset);
586618
if p.isolation_type == IsolationType::None {
@@ -615,8 +647,10 @@ fn shim_main(shim_params_raw_offset: isize) -> ! {
615647
log!("openhcl_boot: early debugging enabled");
616648
}
617649

618-
let can_trust_host =
619-
p.isolation_type == IsolationType::None || static_options.confidential_debug;
650+
let hw_debug_bit = get_hw_debug_bit(p.isolation_type);
651+
let can_trust_host = p.isolation_type == IsolationType::None
652+
|| static_options.confidential_debug
653+
|| hw_debug_bit;
620654

621655
let boot_reftime = get_ref_time(p.isolation_type);
622656

@@ -628,6 +662,12 @@ fn shim_main(shim_params_raw_offset: isize) -> ! {
628662
Err(e) => panic!("unable to read device tree params {}", e),
629663
};
630664

665+
// Confidential debug will show up in boot_options only if included in the
666+
// static command line, or if can_trust_host is true (so the dynamic command
667+
// line has been parsed).
668+
let is_confidential_debug = (can_trust_host && p.isolation_type != IsolationType::None)
669+
|| partition_info.boot_options.confidential_debug;
670+
631671
// Fill out the non-devicetree derived parts of PartitionInfo.
632672
if !p.isolation_type.is_hardware_isolated()
633673
&& hvcall().vtl() == Vtl::Vtl2
@@ -697,6 +737,7 @@ fn shim_main(shim_params_raw_offset: isize) -> ! {
697737
&mut cmdline,
698738
partition_info,
699739
can_trust_host,
740+
is_confidential_debug,
700741
sidecar.as_ref(),
701742
)
702743
.unwrap();

openhcl/underhill_core/src/worker.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ use tracing::Instrument;
127127
use tracing::instrument;
128128
use uevent::UeventListener;
129129
use underhill_attestation::AttestationType;
130+
use underhill_confidentiality::confidential_debug_enabled;
130131
use underhill_threadpool::AffinitizedThreadpool;
131132
use underhill_threadpool::ThreadpoolBuilder;
132133
use virt::Partition;
@@ -1589,6 +1590,10 @@ async fn new_underhill_vm(
15891590
);
15901591
}
15911592

1593+
if confidential_debug_enabled() {
1594+
tracing::warn!(CVM_ALLOWED, "confidential debug enabled");
1595+
}
1596+
15921597
// Create the `AttestationVmConfig` from `dps`, which will be used in
15931598
// - stateful mode (the attestation is not suppressed)
15941599
// - stateless mode (isolated VM with attestation suppressed)

support/tdx_guest_device/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ name = "tdx_guest_device"
66
edition.workspace = true
77
rust-version.workspace = true
88

9+
[features]
10+
std = []
11+
912
[dependencies]
13+
bitfield-struct.workspace = true
1014
static_assertions.workspace = true
1115
zerocopy.workspace = true
1216
[target.'cfg(target_os = "linux")'.dependencies]

support/tdx_guest_device/src/ioctl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
//! The module implements the Linux TDX Guest APIs based on ioctl.
55
6+
#![cfg(feature = "std")]
67
// UNSAFETY: unsafe needed to make ioctl calls.
78
#![expect(unsafe_code)]
89

support/tdx_guest_device/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//! The crate includes the abstraction layer of Linux TDX Guest APIs and
55
//! definitions of data structures according to TDX specification.
66
7+
#![cfg_attr(not(feature = "std"), no_std)]
8+
79
pub mod protocol;
810

911
#[cfg(target_os = "linux")]

support/tdx_guest_device/src/protocol.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
//! The module includes the definitions of data structures according to TDX specification.
55
6+
use bitfield_struct::bitfield;
67
use zerocopy::FromBytes;
78
use zerocopy::Immutable;
89
use zerocopy::IntoBytes;
@@ -135,12 +136,52 @@ pub struct TdInfo {
135136
/// Run-time extendable measurement register.
136137
pub type Rtmr = [u8; 48];
137138

139+
/// See `ATTRIBUTES` in Table 3.9, "Intel TDX Module v1.5 ABI specification", March 2024.
140+
#[bitfield(u64)]
141+
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
142+
pub struct TdAttributes {
143+
#[bits(1)]
144+
pub debug: bool,
145+
#[bits(3)]
146+
_reserved1: u8,
147+
#[bits(1)]
148+
pub hgs_plus_prof: bool,
149+
#[bits(1)]
150+
pub perf_prof: bool,
151+
#[bits(1)]
152+
pub pmt_prof: bool,
153+
#[bits(9)]
154+
_reserved2: u16,
155+
#[bits(7)]
156+
_reserved_p: u8,
157+
#[bits(4)]
158+
_reserved_n: u8,
159+
#[bits(1)]
160+
pub lass: bool,
161+
#[bits(1)]
162+
pub sept_ve_disable: bool,
163+
#[bits(1)]
164+
pub migratable: bool,
165+
#[bits(1)]
166+
pub pks: bool,
167+
#[bits(1)]
168+
pub kl: bool,
169+
#[bits(24)]
170+
_reserved3: u32,
171+
#[bits(6)]
172+
_reserved4: u32,
173+
#[bits(1)]
174+
pub tpa: bool,
175+
#[bits(1)]
176+
pub perfmon: bool,
177+
}
178+
138179
/// See `TDINFO_BASE` in Table 3.34, "Intel TDX Module v1.5 ABI specification", March 2024.
139180
#[repr(C)]
140181
#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
141182
pub struct TdInfoBase {
142183
/// TD's attributes
143-
pub attributes: [u8; 8],
184+
pub attributes: TdAttributes,
144185
/// TD's XFAM
145186
pub xfam: [u8; 8],
146187
/// Measurement of the initial contents of the TDX in SHA384

0 commit comments

Comments
 (0)