From 5e94eb82f053aa033fe62575dc024c2f63dbc091 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 28 Sep 2026 17:02:46 +0200 Subject: [PATCH] Name native identity fields that drift --- src/drivers.rs | 158 ++++++++++++++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 68 deletions(-) diff --git a/src/drivers.rs b/src/drivers.rs index 070df8f..75331bb 100644 --- a/src/drivers.rs +++ b/src/drivers.rs @@ -2407,6 +2407,76 @@ pub struct SystemdTransientWorkloadDriver { pub credential_root: PathBuf, } +fn changed_systemd_workload_fields( + observed: &SystemdWorkloadObservation, + prior: &SystemdWorkloadObservation, +) -> Vec<&'static str> { + let mut changed_fields = Vec::new(); + macro_rules! record_changed_fields { + ($($field:ident),+ $(,)?) => { + $( + if observed.$field != prior.$field { + changed_fields.push(stringify!($field)); + } + )+ + }; + } + record_changed_fields!( + unit, + unit_description, + invocation_id, + exec_main_start_timestamp_monotonic, + service_type, + restart_policy, + kill_mode, + dynamic_user, + systemd_user, + systemd_group, + supplementary_groups, + capability_bounding_set, + ambient_capabilities, + private_mounts, + private_pids, + protect_proc, + proc_subset, + no_new_privileges, + umask, + inaccessible_paths, + load_credential, + main_pid, + process_start_time, + process_uids, + process_gids, + process_groups, + process_cap_inheritable, + process_cap_permitted, + process_cap_effective, + process_cap_bounding, + process_cap_ambient, + process_no_new_privileges, + process_namespace_pids, + mount_namespace_id, + pid_namespace_id, + executable, + executable_device, + executable_inode, + executable_sha256, + runtime_instance_id, + working_directory, + runtime_bundle, + command_line_sha256, + environment_names, + environment_contract_sha256, + control_group, + credentials_directory, + parent_only_file_descriptors, + activation_signer_identity_id, + activation_signer_public_key, + service_credentials, + ); + changed_fields +} + fn systemd_group_matches_launch_contract( expected_group: Option<(&str, u32)>, observed_group: &str, @@ -3859,72 +3929,9 @@ impl WorkloadPort for SystemdTransientWorkloadDriver { &prior.parent_only_file_descriptors, )?; if observed != *prior { - let mut changed_fields = Vec::new(); - macro_rules! record_changed_fields { - ($($field:ident),+ $(,)?) => { - $( - if observed.$field != prior.$field { - changed_fields.push(stringify!($field)); - } - )+ - }; - } - record_changed_fields!( - unit, - unit_description, - invocation_id, - exec_main_start_timestamp_monotonic, - service_type, - restart_policy, - kill_mode, - dynamic_user, - systemd_user, - systemd_group, - supplementary_groups, - capability_bounding_set, - ambient_capabilities, - private_mounts, - private_pids, - protect_proc, - proc_subset, - no_new_privileges, - umask, - inaccessible_paths, - load_credential, - main_pid, - process_start_time, - process_uids, - process_gids, - process_groups, - process_cap_inheritable, - process_cap_permitted, - process_cap_effective, - process_cap_bounding, - process_cap_ambient, - process_no_new_privileges, - process_namespace_pids, - mount_namespace_id, - pid_namespace_id, - executable, - executable_device, - executable_inode, - executable_sha256, - runtime_instance_id, - working_directory, - runtime_bundle, - command_line_sha256, - environment_names, - environment_contract_sha256, - control_group, - credentials_directory, - parent_only_file_descriptors, - activation_signer_identity_id, - activation_signer_public_key, - service_credentials, - ); bail!( "native workload identity changed after observation: {}", - changed_fields.join(", ") + changed_systemd_workload_fields(&observed, prior).join(", ") ); } ensure!( @@ -3991,10 +3998,12 @@ impl WorkloadPort for SystemdTransientWorkloadDriver { .collect::>(), &observation.parent_only_file_descriptors, )?; - ensure!( - current == *observation, - "refusing to stop a workload whose native identity changed" - ); + if current != *observation { + bail!( + "refusing to stop a workload whose native identity changed: {}", + changed_systemd_workload_fields(¤t, observation).join(", ") + ); + } } else { ensure!( values.get("InvocationID") == Some(&observation.invocation_id) @@ -8200,6 +8209,19 @@ mod tests { Ok(()) } + #[test] + fn workload_identity_diagnostic_names_only_changed_fields() { + let prior = systemd_audit_observation("no", 61_000); + let mut observed = prior.clone(); + observed.main_pid += 1; + observed.command_line_sha256 = format!("sha256-{}", "f".repeat(64)); + + assert_eq!( + changed_systemd_workload_fields(&observed, &prior), + vec!["main_pid", "command_line_sha256"] + ); + } + #[test] fn host_isolation_is_two_live_distinct_processes_on_one_host() { let live = |pid: u32, created: u64| {