@@ -9,8 +9,9 @@ use std::path::{Path, PathBuf};
99use std:: process:: { Child , Command } ;
1010
1111use crate :: backend:: {
12- BackendKind , EnforcementProof , LaunchSpec , NetworkConfinement , PrepareRequest , SandboxBackend ,
13- SandboxHandle , SandboxMount , SandboxRuntimeLayout ,
12+ BackendKind , BrokerBridgeKind , EnforcementProof , LaunchSpec , NetworkConfinement ,
13+ PrepareRequest , SandboxBackend , SandboxHandle , SandboxMount , SandboxRuntimeLayout ,
14+ SecretShimSupport , SecretShimUnsupportedReason , ShimTarget ,
1415} ;
1516use crate :: config:: { MountSpec , NetworkPolicy , SidecarEndpoint } ;
1617use crate :: error:: RunError ;
@@ -22,7 +23,7 @@ const VZ_GUEST_KERNEL_ENV: &str = "FIRMA_RUN_VZ_GUEST_KERNEL";
2223const VZ_GUEST_INITRD_ENV : & str = "FIRMA_RUN_VZ_GUEST_INITRD" ;
2324const VZ_GUEST_ROOTFS_ENV : & str = "FIRMA_RUN_VZ_GUEST_ROOTFS" ;
2425const VZ_GUEST_LAUNCH_CONTRACT_VERSION : u32 = 1 ;
25- const VZ_GUEST_SECRET_ENV_KEYS : & [ & str ] = & [ "FIRMA_CAPABILITY_TOKEN" ] ;
26+ const VZ_GUEST_SECRET_ENV_KEYS : & [ & str ] = & [ "FIRMA_CAPABILITY_TOKEN" , "FIRMA_BROKER_ADDR" ] ;
2627const VZ_GUEST_HOST_NETWORK_ENV_KEYS : & [ & str ] = & [
2728 "HTTP_PROXY" ,
2829 "HTTPS_PROXY" ,
@@ -40,6 +41,7 @@ const VZ_GUEST_DNS_STUB_ADDR: &str = "127.0.0.1:1053";
4041const VZ_GUEST_SIDECAR_VSOCK_PORT : u32 = 18080 ;
4142const VZ_GUEST_COMMAND_PTY_VSOCK_PORT : u32 = 18081 ;
4243const VZ_GUEST_COMMAND_PTY_CONTROL_VSOCK_PORT : u32 = 18082 ;
44+ const VZ_GUEST_BROKER_VSOCK_PORT : u32 = 18083 ;
4345
4446/// Host paths owned by the VZ guest-launch handoff.
4547struct VzGuestLayout {
@@ -269,7 +271,7 @@ impl SandboxBackend for VzBackend {
269271
270272 let mode = vz_structural_mode ( ) ;
271273 if mode == VzStructuralMode :: VzGuest {
272- return start_vz_guest_runner ( handle, launch) ;
274+ return start_vz_guest_runner ( handle, launch, & self . secret_shim_support ( ) ) ;
273275 }
274276
275277 let mut command = Command :: new ( "sandbox-exec" ) ;
@@ -309,6 +311,23 @@ impl SandboxBackend for VzBackend {
309311 remove_runtime_dir ( & handle. runtime_dir ) ;
310312 Ok ( ( ) )
311313 }
314+
315+ fn secret_shim_support ( & self ) -> SecretShimSupport {
316+ let mode = vz_structural_mode ( ) ;
317+ match mode {
318+ VzStructuralMode :: Compatibility | VzStructuralMode :: SandboxExecNetworkDeny => {
319+ SecretShimSupport :: Unsupported {
320+ reason : SecretShimUnsupportedReason :: HostCallable ,
321+ }
322+ }
323+ VzStructuralMode :: VzGuest => SecretShimSupport :: IsolatedGuest {
324+ guest_target : ShimTarget :: linux_x86_64_musl ( ) ,
325+ broker_bridge : BrokerBridgeKind :: VsockPort {
326+ port : VZ_GUEST_BROKER_VSOCK_PORT ,
327+ } ,
328+ } ,
329+ }
330+ }
312331}
313332
314333/// Create the VZ runtime tree with owner-only custody.
@@ -377,6 +396,8 @@ struct VzGuestLaunchContract {
377396 mounts : Vec < MountSpec > ,
378397 network : VzGuestNetworkContract ,
379398 invariants : Vec < VzGuestInvariantContract > ,
399+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
400+ secret_shims : Option < VzGuestSecretShimsContract > ,
380401}
381402
382403impl VzGuestLaunchContract {
@@ -385,12 +406,14 @@ impl VzGuestLaunchContract {
385406 handle : & SandboxHandle ,
386407 launch : & LaunchSpec ,
387408 inputs : VzGuestLaunchInputs ,
409+ shim_support : & SecretShimSupport ,
388410 ) -> Result < Self , RunError > {
389411 Self :: from_launch_with_terminal_snapshot (
390412 handle,
391413 launch,
392414 inputs,
393415 TerminalSnapshot :: from_host ( ) ,
416+ shim_support,
394417 )
395418 }
396419
@@ -399,10 +422,26 @@ impl VzGuestLaunchContract {
399422 launch : & LaunchSpec ,
400423 inputs : VzGuestLaunchInputs ,
401424 terminal_snapshot : TerminalSnapshot ,
425+ shim_support : & SecretShimSupport ,
402426 ) -> Result < Self , RunError > {
403427 let terminal =
404428 VzGuestTerminalContract :: from_launch_with_terminal_snapshot ( launch, terminal_snapshot) ;
405429
430+ let secret_shims = match shim_support {
431+ SecretShimSupport :: IsolatedGuest {
432+ guest_target,
433+ broker_bridge,
434+ } => Some ( VzGuestSecretShimsContract {
435+ guest_target_triple : guest_target. triple . to_string ( ) ,
436+ provider_names : vz_guest_shim_provider_names ( & launch. env ) ,
437+ broker_vsock_port : match broker_bridge {
438+ BrokerBridgeKind :: VsockPort { port } => * port,
439+ } ,
440+ shim_share_directory : handle. runtime_dir . join ( "vz-guest" ) . join ( "secret-shims" ) ,
441+ } ) ,
442+ SecretShimSupport :: HostBindMount { .. } | SecretShimSupport :: Unsupported { .. } => None ,
443+ } ;
444+
406445 Ok ( Self {
407446 version : VZ_GUEST_LAUNCH_CONTRACT_VERSION ,
408447 sandbox_id : handle. identity . sandbox_id . to_string ( ) ,
@@ -434,6 +473,7 @@ impl VzGuestLaunchContract {
434473 handle. identity . full_attribution_headers ( ) ,
435474 ) ?,
436475 invariants : VzGuestInvariantContract :: required_set ( handle. network_policy . fail_closed ) ,
476+ secret_shims,
437477 } )
438478 }
439479}
@@ -714,18 +754,42 @@ enum VzGuestInvariantMode {
714754 DisabledByPolicy ,
715755}
716756
717- fn start_vz_guest_runner ( handle : & SandboxHandle , launch : & LaunchSpec ) -> Result < Child , RunError > {
757+ #[ derive( Debug , serde:: Serialize ) ]
758+ #[ serde( rename_all = "snake_case" ) ]
759+ struct VzGuestSecretShimsContract {
760+ guest_target_triple : String ,
761+ provider_names : Vec < String > ,
762+ broker_vsock_port : u32 ,
763+ shim_share_directory : PathBuf ,
764+ }
765+
766+ /// Extracts the provider names that need shims from the launch environment.
767+ ///
768+ /// Provider names are communicated via the `FIRMA_SECRET_PROVIDER_NAMES` env
769+ /// var set by `secret_shims::prepare` when it sets up the broker.
770+ fn vz_guest_shim_provider_names ( env : & BTreeMap < String , String > ) -> Vec < String > {
771+ env. get ( "FIRMA_SECRET_PROVIDER_NAMES" )
772+ . map ( |value| value. split ( ',' ) . map ( str:: to_string) . collect ( ) )
773+ . unwrap_or_default ( )
774+ }
775+
776+ fn start_vz_guest_runner (
777+ handle : & SandboxHandle ,
778+ launch : & LaunchSpec ,
779+ shim_support : & SecretShimSupport ,
780+ ) -> Result < Child , RunError > {
718781 let inputs = VzGuestLaunchInputs :: from_env ( ) ?;
719- start_vz_guest_runner_with_inputs ( handle, launch, inputs)
782+ start_vz_guest_runner_with_inputs ( handle, launch, inputs, shim_support )
720783}
721784
722785fn start_vz_guest_runner_with_inputs (
723786 handle : & SandboxHandle ,
724787 launch : & LaunchSpec ,
725788 inputs : VzGuestLaunchInputs ,
789+ shim_support : & SecretShimSupport ,
726790) -> Result < Child , RunError > {
727791 let runner = inputs. runner . clone ( ) ;
728- let contract = VzGuestLaunchContract :: from_launch ( handle, launch, inputs) ?;
792+ let contract = VzGuestLaunchContract :: from_launch ( handle, launch, inputs, shim_support ) ?;
729793 let contract_path = write_vz_guest_launch_contract ( handle, & contract) ?;
730794
731795 tracing:: info!(
@@ -1026,7 +1090,8 @@ mod tests {
10261090 use crate :: identity:: RunIdentity ;
10271091
10281092 use super :: {
1029- GuestPtyRequest , GuestTerminalSelection , TerminalSize , TerminalSnapshot ,
1093+ BrokerBridgeKind , GuestPtyRequest , GuestTerminalSelection , SecretShimSupport , ShimTarget ,
1094+ TerminalSize , TerminalSnapshot , VZ_GUEST_BROKER_VSOCK_PORT ,
10301095 VZ_GUEST_COMMAND_PTY_CONTROL_VSOCK_PORT , VZ_GUEST_COMMAND_PTY_VSOCK_PORT ,
10311096 VzGuestLaunchContract , VzGuestLaunchInputs , VzGuestLayout , VzGuestTerminalContract ,
10321097 VzStructuralMode , build_sandbox_profile, loopback_port_from, vz_structural_mode_from_flags,
@@ -1101,6 +1166,12 @@ mod tests {
11011166 initrd : PathBuf :: from ( "/var/lib/firma/vz/initrd.img" ) ,
11021167 rootfs : PathBuf :: from ( "/var/lib/firma/vz/rootfs.img" ) ,
11031168 } ,
1169+ & SecretShimSupport :: IsolatedGuest {
1170+ guest_target : ShimTarget :: linux_x86_64_musl ( ) ,
1171+ broker_bridge : BrokerBridgeKind :: VsockPort {
1172+ port : VZ_GUEST_BROKER_VSOCK_PORT ,
1173+ } ,
1174+ } ,
11041175 )
11051176 . expect ( "guest contract should build from prepared launch" )
11061177 }
@@ -1212,6 +1283,12 @@ mod tests {
12121283 rootfs : PathBuf :: from ( "/var/lib/firma/vz/rootfs.img" ) ,
12131284 } ,
12141285 terminal_snapshot,
1286+ & SecretShimSupport :: IsolatedGuest {
1287+ guest_target : ShimTarget :: linux_x86_64_musl ( ) ,
1288+ broker_bridge : BrokerBridgeKind :: VsockPort {
1289+ port : VZ_GUEST_BROKER_VSOCK_PORT ,
1290+ } ,
1291+ } ,
12151292 )
12161293 . expect ( "guest contract should build from prepared launch" ) ;
12171294
@@ -1257,6 +1334,7 @@ mod tests {
12571334 "runner" ,
12581335 "runtime_dir" ,
12591336 "sandbox_id" ,
1337+ "secret_shims" ,
12601338 "terminal" ,
12611339 "version" ,
12621340 ] )
@@ -1687,6 +1765,12 @@ mod tests {
16871765 initrd : PathBuf :: from ( "/var/lib/firma/vz/initrd.img" ) ,
16881766 rootfs : PathBuf :: from ( "/var/lib/firma/vz/rootfs.img" ) ,
16891767 } ,
1768+ & SecretShimSupport :: IsolatedGuest {
1769+ guest_target : ShimTarget :: linux_x86_64_musl ( ) ,
1770+ broker_bridge : BrokerBridgeKind :: VsockPort {
1771+ port : VZ_GUEST_BROKER_VSOCK_PORT ,
1772+ } ,
1773+ } ,
16901774 )
16911775 . expect ( "guest contract should build from prepared launch" ) ;
16921776
@@ -1813,6 +1897,12 @@ mod tests {
18131897 initrd : PathBuf :: from ( "/var/lib/firma/vz/initrd.img" ) ,
18141898 rootfs : PathBuf :: from ( "/var/lib/firma/vz/rootfs.img" ) ,
18151899 } ,
1900+ & SecretShimSupport :: IsolatedGuest {
1901+ guest_target : ShimTarget :: linux_x86_64_musl ( ) ,
1902+ broker_bridge : BrokerBridgeKind :: VsockPort {
1903+ port : VZ_GUEST_BROKER_VSOCK_PORT ,
1904+ } ,
1905+ } ,
18161906 )
18171907 . expect_err ( "non-loopback sidecar endpoint must fail closed" ) ;
18181908
@@ -1881,6 +1971,12 @@ mod tests {
18811971 initrd : PathBuf :: from ( "/var/lib/firma/vz/initrd.img" ) ,
18821972 rootfs : PathBuf :: from ( "/var/lib/firma/vz/rootfs.img" ) ,
18831973 } ,
1974+ & SecretShimSupport :: IsolatedGuest {
1975+ guest_target : ShimTarget :: linux_x86_64_musl ( ) ,
1976+ broker_bridge : BrokerBridgeKind :: VsockPort {
1977+ port : VZ_GUEST_BROKER_VSOCK_PORT ,
1978+ } ,
1979+ } ,
18841980 )
18851981 . expect ( "guest contract should build from prepared launch" ) ;
18861982
@@ -1965,6 +2061,12 @@ mod tests {
19652061 initrd : initrd. clone ( ) ,
19662062 rootfs : rootfs. clone ( ) ,
19672063 } ,
2064+ & SecretShimSupport :: IsolatedGuest {
2065+ guest_target : ShimTarget :: linux_x86_64_musl ( ) ,
2066+ broker_bridge : BrokerBridgeKind :: VsockPort {
2067+ port : VZ_GUEST_BROKER_VSOCK_PORT ,
2068+ } ,
2069+ } ,
19682070 )
19692071 . expect ( "fake VZ runner should spawn" ) ;
19702072 let status = child. wait ( ) . expect ( "fake VZ runner should exit" ) ;
0 commit comments