@@ -419,23 +419,24 @@ fn find_event_payloads(runtime_events: &[RuntimeEvent], name: &str) -> Vec<Vec<u
419419 . collect ( )
420420}
421421
422- fn decode_vm_config_with_fallback ( config : & str , fallback_config : & str ) -> Result < VmConfig > {
423- let config = if config. is_empty ( ) {
424- fallback_config
425- } else {
426- config
427- } ;
428- let config = if config. is_empty ( ) { "{}" } else { config } ;
429- let config = vm_config_json_from_config ( config) . unwrap_or ( Cow :: Borrowed ( config) ) ;
430- serde_json:: from_str ( & config) . context ( "Failed to parse vm config" )
422+ /// The VM config to decode: the caller-supplied copy or the one carried in the
423+ /// attestation. When both are given they must be identical, so no reader can
424+ /// authorize on one copy and decode another.
425+ pub fn resolve_vm_config < ' a > ( external : & ' a str , embedded : & ' a str ) -> Result < & ' a str > {
426+ if external. is_empty ( ) {
427+ return Ok ( embedded) ;
428+ }
429+ if !embedded. is_empty ( ) && external != embedded {
430+ bail ! ( "vm_config does not match the config carried in the attestation" ) ;
431+ }
432+ Ok ( external)
431433}
432434
433- fn vm_config_json_from_config ( config : & str ) -> Option < Cow < ' _ , str > > {
434- let value = serde_json:: from_str :: < serde_json:: Value > ( config) . ok ( ) ?;
435- value
436- . get ( "vm_config" )
437- . and_then ( |value| value. as_str ( ) )
438- . map ( |vm_config| Cow :: Owned ( vm_config. to_string ( ) ) )
435+ fn decode_vm_config_with_fallback ( config : & str , fallback_config : & str ) -> Result < VmConfig > {
436+ let config = resolve_vm_config ( config, fallback_config) ?;
437+ // No vm config for nitro enclave
438+ let config = if config. is_empty ( ) { "{}" } else { config } ;
439+ serde_json:: from_str ( config) . context ( "Failed to parse vm config" )
439440}
440441
441442fn mr_config_document_from_value ( value : & serde_json:: Value ) -> Result < Option < String > > {
@@ -453,16 +454,7 @@ fn mr_config_document_from_config(config: &str) -> Result<Option<String>> {
453454 let Ok ( value) = serde_json:: from_str :: < serde_json:: Value > ( config) else {
454455 return Ok ( None ) ;
455456 } ;
456- if let Some ( mr_config) = mr_config_document_from_value ( & value) ? {
457- return Ok ( Some ( mr_config) ) ;
458- }
459-
460- let Some ( vm_config) = value. get ( "vm_config" ) . and_then ( |value| value. as_str ( ) ) else {
461- return Ok ( None ) ;
462- } ;
463- let vm_config = serde_json:: from_str :: < serde_json:: Value > ( vm_config)
464- . context ( "Failed to parse nested vm_config for amd sev-snp mr_config" ) ?;
465- mr_config_document_from_value ( & vm_config)
457+ mr_config_document_from_value ( & value)
466458}
467459
468460pub use dstack_types:: TeeVariant ;
@@ -1685,20 +1677,18 @@ fn decode_app_info_sev_snp(
16851677 external_vm_config : & str ,
16861678) -> Result < AppInfo > {
16871679 let parsed = crate :: amd_sev_snp:: parse_unverified_amd_snp_report ( report) ?;
1680+ let config = resolve_vm_config ( external_vm_config, embedded_config) ?;
16881681 let mr_config_document = if let Some ( mr_config) = mr_config {
16891682 Cow :: Borrowed ( mr_config)
1690- } else if let Some ( mr_config) = mr_config_document_from_config ( external_vm_config) ? {
1691- Cow :: Owned ( mr_config)
1692- } else if let Some ( mr_config) = mr_config_document_from_config ( embedded_config) ? {
1683+ } else if let Some ( mr_config) = mr_config_document_from_config ( config) ? {
16931684 Cow :: Owned ( mr_config)
16941685 } else {
16951686 bail ! ( "amd sev-snp mr_config is missing" ) ;
16961687 } ;
16971688 let mr_config = verify_snp_mr_config_host_data ( mr_config_document. as_ref ( ) , & parsed. host_data ) ?;
16981689
16991690 let key_provider_info = key_provider_info_from_mr_config ( & mr_config) ?;
1700- let os_image_hash =
1701- decode_vm_config_with_fallback ( external_vm_config, embedded_config) ?. os_image_hash ;
1691+ let os_image_hash = decode_vm_config_with_fallback ( config, "" ) ?. os_image_hash ;
17021692 let mrs = decode_mr_sev_snp ( & parsed. measurement , & parsed. host_data ) ;
17031693
17041694 Ok ( AppInfo {
@@ -1983,17 +1973,8 @@ impl<T: GetDeviceId> Attestation<T> {
19831973 }
19841974
19851975 /// Decode the VM config from the external or embedded config
1986- pub fn decode_vm_config < ' a > ( & ' a self , mut config : & ' a str ) -> Result < VmConfig > {
1987- if config. is_empty ( ) {
1988- config = & self . config ;
1989- }
1990- if config. is_empty ( ) {
1991- // No vm config for nitro enclave
1992- config = "{}" ;
1993- }
1994- let vm_config: VmConfig =
1995- serde_json:: from_str ( config) . context ( "Failed to parse vm config" ) ?;
1996- Ok ( vm_config)
1976+ pub fn decode_vm_config ( & self , config : & str ) -> Result < VmConfig > {
1977+ decode_vm_config_with_fallback ( config, & self . config )
19971978 }
19981979
19991980 /// Decode the app info from the platform-specific app info source.
0 commit comments