From f56d7455ad8cddf14f108136453b0275579c8885 Mon Sep 17 00:00:00 2001 From: Enrique Saurez Date: Mon, 26 Oct 2026 11:04:35 -0700 Subject: [PATCH 1/2] nvx-rs: give each network policy a template of its own A template's NIC is restored with the network that its capture attached, so a template serves the clones of that network alone. Until now, a clone's plan checked only that the template had a NIC when the clone's plan had a network, at the guest address of that NIC, and the restore then passed the policy of the clone's own network, which OpenVMM refused at the restore if it was another. The template key now holds the network as the capture class lowered it to OpenVMM's arguments, `--net` with the guest's address, then the options of the policy, and none for a template without a NIC, so the no-network identity is shared by a closed network. Its canonical encoding takes the list as its eighth part and stays version 1: the encoding has not been released, so a template store that an earlier build created is not supported, and is deleted and created again, since nothing migrates it. A key's network must be exactly the arguments to which a network of a guest at its NIC's address lowers, which decoding checks by reading the policy back and lowering it again, or none for a machine without a NIC; the parsers of OpenVMM's native rules, forwards, and proxy endpoints that it reads with build with the host feature. The key's vectors of version 1 change in place; the class's, whose encoding is unchanged, stay as they are. `ClonePlan` compares the lowering of the adapter's plan's network with the key's, in one check that replaces the check of the guest's address, and refuses, before any VMM starts, as a failure of the request with invalid settings, a network for a template without a NIC, none for a template with one, and another policy or guest address. The restore passes the key's network, but `--net` and the address, which OpenVMM takes from the snapshot, so no clone gets ingress, host-loopback access to its listeners, or forwards, which no template's policy allows. The comparison lowers the plan's network, without hashing, and the cold path, which has no template, is unchanged. Part of #846 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 34e6ffe3-3ebf-42db-bfca-e0ecfade6873 --- .../1.5-compatibility-and-versioning-model.md | 8 + nvx-rs/README.md | 74 +++--- nvx-rs/src/host/network/arguments.rs | 27 +- nvx-rs/src/host/network/loopback.rs | 2 - nvx-rs/src/host/network/mod.rs | 1 + nvx-rs/src/host/network/proxy.rs | 1 - nvx-rs/src/host/network/rule.rs | 7 +- nvx-rs/src/host/network/tests.rs | 37 +++ nvx-rs/src/host/template/clone.rs | 115 +++++---- nvx-rs/src/host/template/clone/launch.rs | 33 ++- nvx-rs/src/host/template/clone/tests.rs | 64 ++++- .../src/host/template/clone/tests/launch.rs | 7 +- nvx-rs/src/host/template/key.rs | 153 ++++++++++- nvx-rs/src/host/template/key/tests.rs | 238 +++++++++++++++++- nvx-rs/src/host/template/mod.rs | 6 +- nvx-rs/tests/vectors/README.md | 10 +- nvx-rs/tests/vectors/template-key-v1.txt | 95 ++++--- 17 files changed, 705 insertions(+), 173 deletions(-) diff --git a/doc/design/1.5-compatibility-and-versioning-model.md b/doc/design/1.5-compatibility-and-versioning-model.md index 860545f14..e21b9b863 100644 --- a/doc/design/1.5-compatibility-and-versioning-model.md +++ b/doc/design/1.5-compatibility-and-versioning-model.md @@ -73,6 +73,14 @@ activation ranges. Layer-role presence and device geometry stay fixed: a platform template accepts a substitute layer only with the same recorded logical length and block sizes. +A template's compatibility key also records its network, as OpenVMM's +arguments to which its class lowers it: the guest's address and the policy of +its NIC, which every restore of the template passes unchanged, so a template +serves the clones of its own network policy alone. The key's encoding, version +1, includes that network and has not been released, so a template store that +an earlier build created is not supported: delete it and create a new one. +There is no migration. + ## 1.5.3 Persisted State The snapshot manifest is authoritative for a restored process. Native file diff --git a/nvx-rs/README.md b/nvx-rs/README.md index 6e81ee210..0f7b3315e 100644 --- a/nvx-rs/README.md +++ b/nvx-rs/README.md @@ -589,17 +589,23 @@ other `Invariants`. `TemplateKey::new` checks that the capture made the machine that its class requested, and derives the template's compatibility key, from metadata alone: -the runtime and contract versions through which its clones are restored, and the +the runtime and contract versions through which its clones are restored, the backend, CPU profile and effective CPUID, topology, rates, resources, kernel -command line, disks, and devices of its machine. A capture's own metadata, such -as its time anchor and host, stays out of the key. +command line, disks, and devices of its machine, and its network, as its class +lowered it to OpenVMM's arguments, the guest's address and the policy of its +NIC, which every restore of the template passes unchanged, so that a template +serves the clones of its network policy alone. A capture's own metadata, such as +its time anchor and host, stays out of the key. A key and a class each have one canonical, versioned encoding, whose domain-separated SHA-256 digest is its identity, a `KeyIdentity`, which converts to and from the `nvx::activation::Identity` by which a clone's activation record names its template's key, or a `ClassIdentity`; the [conformance vectors](tests/vectors/README.md) of version 1, -`tests/vectors/template-key-v1.txt`, pin the key's encoding and identity. +`tests/vectors/template-key-v1.txt`, pin both encodings and identities. The +key's encoding, version 1, includes the template's network and has not been +released, so a template store that an earlier build created is not supported: +delete it and create a new one. There is no migration. `Store` keeps the generations of templates that a host published, apart from every sandbox's store, at a location that the adapter chooses: a private @@ -648,32 +654,31 @@ and no launch. `ClonePlan::new` plans a clone under the lock that acquired its lease, before the launch that the lease reserves, from metadata alone: the leased generation, its key, which must speak the current contracts, the boot and control contracts -of the runtime that captured it included, and its snapshot; a network exactly -when the template has a NIC, on the guest network of that NIC, whose address -OpenVMM restores from the snapshot, and under the policy of that NIC, which -OpenVMM checks as it restores it, since the key names the policy only by -OpenVMM's identity of it; a memory target in whole blocks of `MEMORY_BLOCK_SIZE` -from the template's RAM to its capacity; the clone's image, which the check of -its `DistroBinding` opens; its upper, either the caller's scratch image, which -the check of its `ScratchBinding` claims, and which nothing formats, copies, or -reads, or for an upper in RAM a fresh sparse file, `clone-scratch.raw` in the -sandbox's directory, which the release removes; its export, if it has one, an -`ExportPlan` that `filesystem::plan` made for the container root, which must -export exactly one directory, since the template's dormant filesystem slot binds -one directory and no file, and which must neither overlap the template store, by -the paths that the plan and the store's directory resolve to, nor let the guest -write in a directory through which the store's path leads, links included, since -the host reaches the store, and OpenVMM its snapshots, by that path, nor be or -hold the directory of the clone's sandbox, in which the host writes the clone's -records, checks of paths that leave two rules to whoever names the export, as -they leave the directories above the store: the export must not reach the store -through an alias of it that an administrator configures, such as a bind mount or -a mount point of the store, or of a directory above or inside it, a loopback -share, or a hard link of a payload, nor lie inside a directory that a writable -export of another sandbox or clone holds, since OpenVMM resolves an export's -path again at each launch and restore, so that the directories above the -export's directory must be ones that no guest may change, as those above a -clone's block devices must; and a fresh capability. +of the runtime that captured it included, and its snapshot; the template's +network exactly, as its key records it, or none for a template without a NIC, so +that a template serves the clones of its network policy, at its guest's address, +which OpenVMM restores from the snapshot, alone; a memory target in whole blocks +of `MEMORY_BLOCK_SIZE` from the template's RAM to its capacity; the clone's +image, which the check of its `DistroBinding` opens; its upper, either the +caller's scratch image, which the check of its `ScratchBinding` claims, and +which nothing formats, copies, or reads, or for an upper in RAM a fresh sparse +file, `clone-scratch.raw` in the sandbox's directory, which the release removes; +its export, if it has one, an `ExportPlan` that `filesystem::plan` made for the +container root, which must export exactly one directory, since the template's +dormant filesystem slot binds one directory and no file, and which must neither +overlap the template store, by the paths that the plan and the store's directory +resolve to, nor let the guest write in a directory through which the store's +path leads, links included, since the host reaches the store, and OpenVMM its +snapshots, by that path, nor be or hold the directory of the clone's sandbox, in +which the host writes the clone's records, checks of paths that leave two rules +to whoever names the export, as they leave the directories above the store: the +export must not reach the store through an alias of it that an administrator +configures, such as a bind mount or a mount point of the store, or of a +directory above or inside it, a loopback share, or a hard link of a payload, nor +lie inside a directory that a writable export of another sandbox or clone holds, +since OpenVMM resolves an export's path again at each launch and restore, so +that the directories above the export's directory must be ones that no guest may +change, as those above a clone's block devices must; and a fresh capability. It builds the clone's activation record, `ClonePlan::activation`, which the clone's guest applies in place of the configuration that the template captured, @@ -710,10 +715,11 @@ writes the clone's activation record in its canonical encoding, `clone-activation.bin`, from which a caller resends it unchanged; it listens for the VMM's restore-ready event, at the socket `restore.sock` on Linux, and at a named pipe of a random name on Windows; and it runs `supervisor::launch` with -OpenVMM's restore of the clone's devices, its export bound to the dormant slot, -`--mount` with the directory, and its hidden, re-exposed, and writable paths and -its owner, `--restore-snapshot` with the generation's snapshot in place, which -no clone copies or changes, so that clones of one generation restore it at once, +OpenVMM's restore of the clone's devices and of the template's network, as its +key records it, unchanged, its export bound to the dormant slot, `--mount` with +the directory, and its hidden, re-exposed, and writable paths and its owner, +`--restore-snapshot` with the generation's snapshot in place, which no clone +copies or changes, so that clones of one generation restore it at once, `--restore-memory` with the memory target, and `--restore-ready-path`, under the template's backend, CPU profile, and processors, with a boot console that discards its output, as cold boots have, and the control console, but no kernel, diff --git a/nvx-rs/src/host/network/arguments.rs b/nvx-rs/src/host/network/arguments.rs index ce92e5dc0..bd2f2cc66 100644 --- a/nvx-rs/src/host/network/arguments.rs +++ b/nvx-rs/src/host/network/arguments.rs @@ -41,6 +41,30 @@ pub fn openvmm_arguments( let Some(policy) = policy else { return Ok(Vec::new()); }; + lower_policy(policy, guest_network, false) +} + +/// Returns the OpenVMM options of `policy` for a guest at `guest_network`, as +/// [`openvmm_arguments`] renders them, but those of an attached network device for a policy that +/// lets nothing through too, for which [`openvmm_arguments`] attaches none: the options of the +/// same policy with one more allow rule that lowers to no OpenVMM rule, such as one that excepts +/// its whole destination, and which [`openvmm_arguments`] renders with a device. +/// +/// Fails as [`openvmm_arguments`] does. +pub(crate) fn attached_arguments( + policy: &NetworkPolicy, + guest_network: &str, +) -> Result> { + lower_policy(policy, guest_network, true) +} + +/// Returns the OpenVMM options of `policy` for a guest at `guest_network`, as +/// [`openvmm_arguments`] renders them, and, if `attached`, as [`attached_arguments`] does. +fn lower_policy( + policy: &NetworkPolicy, + guest_network: &str, + attached: bool, +) -> Result> { if let Some(proxy) = &policy.proxy { return proxy_arguments(policy, proxy, guest_network); } @@ -62,7 +86,8 @@ pub fn openvmm_arguments( shorter, which leaves an address at which OpenVMM presents host peers to the guest" ))); } - if policy.egress == Access::Deny + if !attached + && policy.egress == Access::Deny && policy.allow.rules.is_empty() && policy.ingress == Access::Deny && policy.host_loopback == HostLoopback::Deny diff --git a/nvx-rs/src/host/network/loopback.rs b/nvx-rs/src/host/network/loopback.rs index d188e143e..257651008 100644 --- a/nvx-rs/src/host/network/loopback.rs +++ b/nvx-rs/src/host/network/loopback.rs @@ -6,7 +6,6 @@ use std::collections::HashSet; use super::address::Family; use super::arguments::guest_subnet; use super::lowering::Rule; -#[cfg(feature = "cli")] use super::rule::parse_port; use super::{Access, MAX_LOOPBACK_FORWARDS, NetworkPolicy}; use crate::error::{Error, Result}; @@ -86,7 +85,6 @@ impl LoopbackForward { /// /// Fails with [`ErrorKind::Unsupported`](crate::ErrorKind::Unsupported) and a message that /// starts with `value`. - #[cfg(feature = "cli")] pub(crate) fn parse(value: &str) -> Result { let refused = |reason: &str| Err(Error::unsupported(format!("{value}: {reason}"))); let fields: Vec<&str> = value.split(':').collect(); diff --git a/nvx-rs/src/host/network/mod.rs b/nvx-rs/src/host/network/mod.rs index 34e7a256e..97e66f854 100644 --- a/nvx-rs/src/host/network/mod.rs +++ b/nvx-rs/src/host/network/mod.rs @@ -33,6 +33,7 @@ pub mod policy; mod proxy; mod rule; +pub(crate) use self::arguments::attached_arguments; pub use self::arguments::openvmm_arguments; pub use self::loopback::{ForwardProtocol, HostLoopback, LoopbackForward}; pub use self::proxy::{NetworkProxy, ProxyScheme}; diff --git a/nvx-rs/src/host/network/proxy.rs b/nvx-rs/src/host/network/proxy.rs index a81cbeed2..f74b54498 100644 --- a/nvx-rs/src/host/network/proxy.rs +++ b/nvx-rs/src/host/network/proxy.rs @@ -109,7 +109,6 @@ impl NetworkProxy { /// /// Fails with [`ErrorKind::Unsupported`](crate::ErrorKind::Unsupported) and a message that /// starts with `endpoint`. - #[cfg(feature = "cli")] pub(crate) fn parse_endpoint(endpoint: &str, gateway: Ipv4Addr) -> Result { let refused = |reason: String| Err(Error::unsupported(format!("{endpoint}: {reason}"))); let Some((address, port)) = endpoint diff --git a/nvx-rs/src/host/network/rule.rs b/nvx-rs/src/host/network/rule.rs index bc0aeeba4..4ecd05837 100644 --- a/nvx-rs/src/host/network/rule.rs +++ b/nvx-rs/src/host/network/rule.rs @@ -2,10 +2,7 @@ //! the parsing of the rules of an action into the rules that the lowering takes. use super::lowering::{self, PortValue, Rule, RuleProtocol}; -#[cfg(feature = "cli")] -use crate::error::Error; -use crate::error::Result; -#[cfg(feature = "cli")] +use crate::error::{Error, Result}; use crate::net::cidr; /// Allow or deny decision of a network posture. @@ -141,7 +138,6 @@ impl EgressRule { /// /// Fails with [`ErrorKind::Unsupported`](crate::ErrorKind::Unsupported) and a message that /// starts with `value`. - #[cfg(feature = "cli")] pub(crate) fn parse_native(value: &str) -> Result { let refused = |reason: &str| Err(Error::unsupported(format!("{value}: {reason}"))); let (destination, selector) = split_native_rule(value); @@ -203,7 +199,6 @@ impl EgressRule { /// splits it: an IPv4 address holds no `:`, so its first `:` starts the selector; a network with a /// prefix ends at the first `:` after its `/`; and an IPv6 address without a prefix ends at the /// last `:` that leaves an IPv6 address before it, since protocol names are not hexadecimal. -#[cfg(feature = "cli")] fn split_native_rule(value: &str) -> (&str, Option<&str>) { let split_at = |index: usize| (&value[..index], Some(&value[index + 1..])); if let Some(slash) = value.find('/') { diff --git a/nvx-rs/src/host/network/tests.rs b/nvx-rs/src/host/network/tests.rs index 9e9a25163..0aaab1937 100644 --- a/nvx-rs/src/host/network/tests.rs +++ b/nvx-rs/src/host/network/tests.rs @@ -14,6 +14,43 @@ fn rules(arguments: &[String], option: &str) -> Vec { .collect() } +#[test] +fn an_attached_lowering_attaches_the_device_of_a_policy_that_lets_nothing_through() { + // An allow rule that excepts its whole destination lowers to no OpenVMM rule, but a policy + // with one attaches its device, closed, as the attached lowering of the same policy + // without that rule renders it. + let excluded = EgressRule { + to: vec![Destination { + cidr: "192.0.2.0/24".to_owned(), + except: vec!["192.0.2.0/24".to_owned()], + }], + ports: Vec::new(), + }; + let denied = NetworkPolicy::new(Access::Deny).with_deny(EgressRule::to("1.2.3.4")); + for closed in [NetworkPolicy::new(Access::Deny), denied] { + assert!( + openvmm_arguments(Some(&closed), "10.0.0.2/24") + .unwrap() + .is_empty() + ); + let excepted = closed.clone().with_allow(excluded.clone()); + let attached = attached_arguments(&closed, "10.0.0.2/24").unwrap(); + assert_eq!( + attached, + openvmm_arguments(Some(&excepted), "10.0.0.2/24").unwrap() + ); + assert_eq!(attached[..2], ["--net", "10.0.0.2/24"]); + } + // The attached lowering of any other policy is its lowering. + let proxied = NetworkPolicy::proxy_only(NetworkProxy::new(3128)); + for policy in [NetworkPolicy::new(Access::Allow), proxied] { + assert_eq!( + attached_arguments(&policy, "10.0.0.2/24").unwrap(), + openvmm_arguments(Some(&policy), "10.0.0.2/24").unwrap() + ); + } +} + #[test] fn default_postures_map_to_portable_profile_options() { assert!(openvmm_arguments(None, "10.0.0.2/24").unwrap().is_empty()); diff --git a/nvx-rs/src/host/template/clone.rs b/nvx-rs/src/host/template/clone.rs index beea42a7b..769790fa0 100644 --- a/nvx-rs/src/host/template/clone.rs +++ b/nvx-rs/src/host/template/clone.rs @@ -82,12 +82,11 @@ pub struct CloneRequest { /// The adapter's plan, which [`SandboxPlan::adapter`] makes, of the clone's image, its /// `distro`, an EROFS layer or a GPT disk, over its upper: in RAM, a tmpfs, as /// [`SandboxUpper::RAM`](crate::host::sandbox::SandboxUpper::RAM) plans it, or on the - /// caller's scratch image. Its network is the one of the template's NIC, which every restore - /// of the template attaches, or none for a template without a NIC: on the NIC's guest - /// network, which [`ClonePlan::new`] checks, and under the NIC's policy, which OpenVMM checks - /// as it restores the NIC, since the template's key names the policy only by OpenVMM's - /// identity of it. OpenVMM refuses to restore a clone under another policy, which ends its - /// launch once it began. + /// caller's scratch image. Its network must be the template's, which every restore of the + /// template attaches unchanged, as [`ClonePlan::new`] checks: the network that the template's + /// class lowered to OpenVMM's arguments, as its key records it, + /// [`TemplateKey::network_arguments`], or for a template without a NIC none, or one that lets + /// nothing through, which attaches none either. pub adapter: SandboxPlan, /// The binding of the image. pub binding: DistroBinding, @@ -195,6 +194,15 @@ pub enum CloneUpper { /// the checked image, and with it the claim. Nothing reads, formats, or copies the image. /// - The memory target must be whole blocks of [`MEMORY_BLOCK_SIZE`], and of the template's own /// memory blocks, from the template's RAM to its RAM capacity. +/// - The network of the adapter's plan must be the template's: lowered to OpenVMM's arguments, as +/// [`SandboxNetwork::openvmm_arguments`](crate::host::sandbox::SandboxNetwork::openvmm_arguments) +/// lowers it, it must be the network that the template's key records, +/// [`TemplateKey::network_arguments`], the guest's address and the policy of the template's NIC, +/// or none for a template without a NIC. A template serves the clones of its network policy +/// alone, and the restore passes the template's network unchanged, as the key records it, so no +/// clone has ingress, host-loopback access to its listeners, or forwards, which no template's +/// policy allows: a template's capture refuses a policy that allows ingress, or host-loopback +/// access both ways, which forwards need. /// - The export, if the request has one, must be a plan that [`filesystem::plan`] could have made /// for the container root, as [`ExportPlan::check`] finds it, of exactly one child, a /// directory: a template's filesystem slot is dormant, and a restore binds one directory to it, @@ -304,8 +312,8 @@ pub struct ClonePlan { activation: ActivationRecord, /// The capability of the clone's launch. capability: [u8; CAPABILITY_LEN], - /// The clone's devices, which its restore attaches: the adapter's plan of its image and - /// network, over the file of its `scratch` block device. + /// The clone's devices, which its restore attaches with the template's network: the adapter's + /// plan of its image, over the file of its `scratch` block device. devices: SandboxPlan, /// The clone's export, which its restore binds to the template's dormant filesystem slot, if /// it has one. @@ -394,10 +402,12 @@ impl ClonePlan { /// one that holds more than a key may; /// - with [`ErrorKind::Unsupported`] for a request that the template cannot serve: a template /// whose key names other contracts than this build speaks, the boot and control contracts - /// of the runtime that captured it included, [`Evidence::IncompatibleHost`]; a plan with a - /// network for a template without a NIC, without one for a template with a NIC, or with - /// another guest network than the template's NIC, whose address OpenVMM restores from the - /// snapshot, [`Evidence::InvalidSettings`]; and a memory target that is not whole blocks of + /// of the runtime that captured it included, [`Evidence::IncompatibleHost`]; a plan whose + /// network is not the template's, as the template's key records it, + /// [`TemplateKey::network_arguments`]: a network for a template without a NIC, none for a + /// template with a NIC, or one with another guest network than the template's NIC, whose + /// address OpenVMM restores from the snapshot, or another policy, + /// [`Evidence::InvalidSettings`]; and a memory target that is not whole blocks of /// [`MEMORY_BLOCK_SIZE`] and of the template's memory blocks, from the template's RAM to its /// RAM capacity, [`Evidence::InvalidTargets`]; /// - with [`ErrorKind::Io`] for a template whose command line names the DNS server of its @@ -709,15 +719,16 @@ impl fmt::Debug for ClonePlan { } /// Returns the devices of the clone of `request`, whose upper is `upper`: the adapter's plan of its -/// image and network, over the file of its `scratch` block device, which every restore attaches, -/// the sparse file of an upper in RAM included. +/// image, over the file of its `scratch` block device, which every restore attaches, the sparse +/// file of an upper in RAM included. The restore attaches the template's network, which its key +/// records, rather than the plan's, which the plan's check found to be the same. fn devices_of(request: &CloneRequest, upper: &CloneUpper) -> SandboxPlan { let adapter = &request.adapter; let scratch = match upper { CloneUpper::Tmpfs { path } => SandboxUpper::scratch_at(paths::normalized(path)), CloneUpper::Scratch(_) => adapter.upper().clone(), }; - SandboxPlan::adapter(adapter.distro().clone(), scratch).with_network(adapter.network().cloned()) + SandboxPlan::adapter(adapter.distro().clone(), scratch) } /// Refuses a request that no clone takes, as [`ClonePlan::new`] describes, without reading or @@ -923,43 +934,51 @@ fn check_template( )), )); } - // A network that OpenVMM attaches no device for is no NIC, as a capture class's. - let attached = match request.adapter.network() { - None => false, - Some(network) => !network + // A template serves the clones of its own network alone: the guest's address and the policy of + // its NIC, which every restore passes unchanged, or no NIC, which a network that lets nothing + // through attaches no more than none does. OpenVMM restores the guest's address on the NIC + // from the snapshot, so a plan of another address would run on the template's. + let requested = match request.adapter.network() { + None => Vec::new(), + Some(network) => network .openvmm_arguments() - .attribute(Evidence::InvalidSettings)? - .is_empty(), + .attribute(Evidence::InvalidSettings)?, }; - if attached != key.has_network() { - return Err(Fault::new( - Evidence::InvalidSettings, - Error::unsupported(if attached { - format!( - "the adapter's plan of a clone attaches a network, but the template's \ - generation {name} has no NIC" - ) - } else { - format!( - "the template's generation {name} has a NIC, which its clones restore with \ - the network of the adapter's plan, but the plan has none" - ) - }), - )); - } - // OpenVMM restores the guest's address on the NIC from the snapshot, and a clone's launch - // drops the plan's, so the plan must name the template's. - if let Some(network) = request.adapter.network().filter(|_| attached) - && let Some(template) = key.guest_network() - && network.guest_network() != template - { + let template = key.network_arguments(); + if requested != template { + let guest = request + .adapter + .network() + .map(|network| network.guest_network()); + let nic = key.guest_network(); + let problem = if template.is_empty() { + format!( + "the adapter's plan of a clone attaches a network, but the template's \ + generation {name} has no NIC" + ) + } else if requested.is_empty() { + format!( + "the template's generation {name} has a NIC, whose network every clone of it \ + restores, but the adapter's plan of the clone has none" + ) + } else if let Some(guest) = guest + && let Some(nic) = nic.as_deref() + && guest != nic + { + format!( + "the adapter's plan of a clone gives its guest the network {guest}, but the \ + template's generation {name} restores its NIC on {nic}, from its snapshot" + ) + } else { + format!( + "the network of the adapter's plan of a clone is not the one that the template's \ + generation {name} restores its NIC with: a template serves the clones of its \ + own network policy, at its own guest's address, alone" + ) + }; return Err(Fault::new( Evidence::InvalidSettings, - Error::unsupported(format!( - "the adapter's plan of a clone gives its guest the network {}, but the template's \ - generation {name} restores its NIC on {template}, from its snapshot", - network.guest_network() - )), + Error::unsupported(problem), )); } let memory = request.memory; diff --git a/nvx-rs/src/host/template/clone/launch.rs b/nvx-rs/src/host/template/clone/launch.rs index 24470078e..97223c772 100644 --- a/nvx-rs/src/host/template/clone/launch.rs +++ b/nvx-rs/src/host/template/clone/launch.rs @@ -130,10 +130,11 @@ impl ClonePlan { /// The VMM's arguments are those of the clone's devices: the microVM machine, the clone's /// image as the read-only `distro` block device and the file of its `scratch` block device, /// which OpenVMM opens at their paths, as [Block devices by - /// path](crate::host::template::Store#block-devices-by-path) describes, and the policy of the - /// template's NIC, if it has one, without the guest's address, which OpenVMM takes from the - /// snapshot. The clone's export, if it has one, follows, bound to the template's dormant - /// filesystem slot: `--mount` with + /// path](crate::host::template::Store#block-devices-by-path) describes, and the template's + /// network, as its key records it, [`TemplateKey::network_arguments`], the policy of the + /// template's NIC, unchanged, if it has one, without `--net` and the guest's address, which + /// OpenVMM takes from the snapshot. The clone's export, if it has one, follows, bound to the + /// template's dormant filesystem slot: `--mount` with /// [`GUEST_EXPORT`](crate::host::filesystem::GUEST_EXPORT), the exported directory, and its /// mode, `rw` if a mapping writes it, and `ro` otherwise, then its hidden, re-exposed, and /// writable paths, and the caller owner, as its [plan](ClonePlan::export) holds them; without @@ -282,7 +283,7 @@ impl ClonePlan { devices, export, } = self; - let mut devices = device_arguments(&devices) + let mut devices = device_arguments(&devices, &key) .attribute(Evidence::InvalidSettings) .map_err(unrecorded)?; let table = match &export { @@ -648,24 +649,22 @@ fn check_sparse(path: &Path, scratch: BlockGeometry) -> Result<(), Fault> { ) } -/// Returns OpenVMM's arguments of the devices of a clone's restore, `devices`: those that -/// [`SandboxPlan::openvmm_arguments`] renders, without `--net` and the guest's address, which -/// OpenVMM takes from the snapshot, and refuses beside it. The options of the network's policy -/// stay: OpenVMM compares the policy that they name with the one of the snapshot's NIC, and -/// refuses to restore under another, so the plan must keep its template NIC's policy, as -/// [`CloneRequest::adapter`](super::CloneRequest::adapter) says, and a plan of another one fails -/// closed, ending the launch. -fn device_arguments(devices: &SandboxPlan) -> Result> { +/// Returns OpenVMM's arguments of the devices of a clone's restore: those of the clone's devices, +/// `devices`, which [`SandboxPlan::openvmm_arguments`] renders, then the template's network, as +/// `key` records it, [`TemplateKey::network_arguments`], without `--net` and the guest's address, +/// which OpenVMM takes from the snapshot, and refuses beside it. The options of the network's +/// policy stay: OpenVMM compares the policy that they name with the one of the snapshot's NIC. +fn device_arguments(devices: &SandboxPlan, key: &TemplateKey) -> Result> { let mut arguments = devices.openvmm_arguments()?; - if let Some(at) = arguments.iter().position(|argument| argument == "--net") { - arguments.drain(at..(at + 2).min(arguments.len())); - } + // A key's network attaches its NIC first, with `--net` and the guest's address. + arguments.extend_from_slice(key.network_arguments().get(2..).unwrap_or_default()); Ok(arguments) } /// What OpenVMM's arguments of a clone's restore name besides its control endpoint. struct Restore<'a> { - /// The arguments of the clone's devices, as [`device_arguments`] renders them. + /// The arguments of the clone's devices and of the template's network, as + /// [`device_arguments`] renders them. devices: Vec, /// The generation's key. key: &'a TemplateKey, diff --git a/nvx-rs/src/host/template/clone/tests.rs b/nvx-rs/src/host/template/clone/tests.rs index 676bf5306..f125f08da 100644 --- a/nvx-rs/src/host/template/clone/tests.rs +++ b/nvx-rs/src/host/template/clone/tests.rs @@ -19,7 +19,9 @@ use crate::activation::{ Publication, Upper, WorkloadIdentity, }; use crate::host::filesystem; -use crate::host::network::{Access as NetworkAccess, NetworkPolicy, NetworkProxy, ProxyScheme}; +use crate::host::network::{ + Access as NetworkAccess, EgressRule, NetworkPolicy, NetworkProxy, ProxyScheme, +}; use crate::host::paths; use crate::host::sandbox::distro::{DISTRO_POLICY_REVISION, PolicyVerdict}; use crate::host::sandbox::scratch::CLAIM_RELEASE_WAIT; @@ -2048,8 +2050,8 @@ fn networks_that_the_template_does_not_have_are_refused() { ( ErrorKind::Unsupported, format!( - "the template's generation {generation} has a NIC, which its clones restore with \ - the network of the adapter's plan, but the plan has none" + "the template's generation {generation} has a NIC, whose network every clone of \ + it restores, but the adapter's plan of the clone has none" ) ) ); @@ -2077,6 +2079,37 @@ fn networks_that_the_template_does_not_have_are_refused() { ); assert_untouched(&acquired); } + // Nor does it serve the clones of another policy at its address: a template serves the clones + // of its own network alone. + let proxy = NetworkProxy::new(3128).with_scheme(ProxyScheme::Http); + for other in [ + network(NetworkAccess::Allow) + .policy() + .clone() + .with_deny(EgressRule::to("192.0.2.0/24")), + NetworkPolicy::new(NetworkAccess::Deny).with_allow(EgressRule::to("192.0.2.0/24")), + NetworkPolicy::proxy_only(proxy), + ] { + let other = with_network( + request.clone(), + Some(SandboxNetwork::new("10.0.0.2/24", other).unwrap()), + ); + assert_eq!( + refused( + fixture.plan(&mut acquired, &other, NO_CONTENT), + Evidence::InvalidSettings + ), + ( + ErrorKind::Unsupported, + format!( + "the network of the adapter's plan of a clone is not the one that the \ + template's generation {generation} restores its NIC with: a template serves \ + the clones of its own network policy, at its own guest's address, alone" + ) + ) + ); + assert_untouched(&acquired); + } let attached = with_network(request, Some(network(NetworkAccess::Allow))); drop(fixture.plan(&mut acquired, &attached, NO_CONTENT).unwrap()); } @@ -2383,13 +2416,26 @@ fn the_activation_record_of_a_clone_of_a_template_with_a_nic_names_its_policy_an plan.activation().configuration().network.as_ref(), Some(&expected) ); - drop(plan); - // A proxy's URL is the one that the guest sees, at its gateway. + drop((plan, acquired, fixture)); + // A proxy's URL is the one that the guest sees, at its gateway, for a clone of a template + // whose policy has the proxy. let proxy = NetworkProxy::new(3128).with_scheme(ProxyScheme::Http); - let proxied = with_network( - tmpfs_request(&image, &binding), - Some(SandboxNetwork::new("10.0.0.2/24", NetworkPolicy::proxy_only(proxy)).unwrap()), - ); + let proxied = SandboxNetwork::new("10.0.0.2/24", NetworkPolicy::proxy_only(proxy)).unwrap(); + let fixture = Fixture::with(|class, spec, physical| { + *class = CaptureClass { + network: Some(proxied.clone()), + ..network_class() + }; + *spec = ManifestSpec::with_network(); + let (distro, scratch) = ( + geometry(IMAGE_LEN, physical), + geometry(SCRATCH_LEN, physical), + ); + set_geometries(class, spec, distro, scratch); + }); + let (image, binding) = fixture.image("distro.erofs", IMAGE_LEN); + let mut acquired = fixture.acquire("sandbox"); + let proxied = with_network(tmpfs_request(&image, &binding), Some(proxied)); let plan = fixture.plan(&mut acquired, &proxied, NO_CONTENT).unwrap(); assert_eq!( plan.activation().configuration().network, diff --git a/nvx-rs/src/host/template/clone/tests/launch.rs b/nvx-rs/src/host/template/clone/tests/launch.rs index b35cd817a..ed492836c 100644 --- a/nvx-rs/src/host/template/clone/tests/launch.rs +++ b/nvx-rs/src/host/template/clone/tests/launch.rs @@ -1019,6 +1019,7 @@ fn a_clone_of_a_template_with_a_nic_restores_its_policy_without_its_address() { let request = with_network(tmpfs_request(&image, &binding), Some(attached.clone())); let plan = fixture.plan(&mut acquired, &request, NO_CONTENT).unwrap(); let runtime = plan.key().runtime().clone(); + let template = plan.key().network_arguments().to_vec(); let mut vmm = VmmDir::new(); let dir = vmm.path().to_owned(); let made = RefCell::new(None); @@ -1031,9 +1032,11 @@ fn a_clone_of_a_template_with_a_nic_restores_its_policy_without_its_address() { .launch_with(&mut acquired, Path::new(OPENVMM), &runtime, hooks) .unwrap(); vmm.reference = Some(restoring.starting().process().reference().clone()); - // The devices end with the arguments of the network's policy, without the guest's address, - // which OpenVMM takes from the snapshot, and refuses beside it. + // The devices end with the template's network, as its key records it, the arguments of the + // network's policy, without the guest's address, which OpenVMM takes from the snapshot, and + // refuses beside it. let mut policy = attached.openvmm_arguments().unwrap(); + assert_eq!(template, policy); assert_eq!(policy[..2], ["--net", "10.0.0.2/24"]); policy.drain(..2); let arguments = made.take().unwrap().arguments; diff --git a/nvx-rs/src/host/template/key.rs b/nvx-rs/src/host/template/key.rs index 419bb658f..056826faa 100644 --- a/nvx-rs/src/host/template/key.rs +++ b/nvx-rs/src/host/template/key.rs @@ -18,6 +18,10 @@ use super::manifest::{ use crate::activation; use crate::contract; use crate::error::{Error, Result}; +use crate::host::network::{ + Access, EgressRule, HostLoopback, LoopbackForward, MAX_LOOPBACK_FORWARDS, MAX_RULES, + NetworkPolicy, NetworkProxy, +}; use crate::host::platform::parse_hex32; use crate::host::sandbox::SandboxNetwork; use crate::host::sandbox::mount::MOUNT_TAG; @@ -38,6 +42,12 @@ const HOST_GENERATION: &str = "host"; /// which OpenVMM writes once at most, with an IP address in its canonical spelling. const DNS_TOKEN: &str = "virtnet_dns="; +/// Most texts of a key's network: the options of OpenVMM that a network lowers to, each with its +/// value, as [`SandboxNetwork::openvmm_arguments`] renders them. A network has at most six options +/// of its own, from `--net` to `--network-proxy`, at most [`MAX_RULES`] rules of each of the two +/// actions of its egress, and at most [`MAX_LOOPBACK_FORWARDS`] host-loopback forwards. +const MAX_NETWORK_ARGUMENTS: usize = 2 * (6 + 2 * MAX_RULES + MAX_LOOPBACK_FORWARDS); + /// The versions of the contracts of a template's clones that its runtime identity does not /// record: the snapshot format, the saved device state, the time ABI, the restore packet, and the /// activation record. @@ -541,11 +551,18 @@ impl CaptureClass { /// addresses, addresses, prefixes, and gateways, with the identity of the network policy that /// OpenVMM enforces there; and the template's [`Invariants`], its other invariant isolation and /// resource settings. +/// - **Network:** the template's network as its class lowers it to OpenVMM's arguments, +/// [`SandboxNetwork::openvmm_arguments`], none for a template without a NIC: the guest's +/// address and the network policy as this crate writes them, which a clone's plan compares with +/// the network of the clone's own plan, and which every restore of the template passes +/// unchanged. A template serves the clones of its network policy alone, so a host keeps one +/// template of each policy that its clones take. /// /// A capture's own metadata is not part of it, so the generations of one key differ in it: when /// the capture was taken, its time contract's anchor, host, boot, and lineage counter, and the /// lengths of its artifacts. [`TemplateManifest`] keeps them. Nothing of a clone is part of it -/// either: its image, upper, export, network settings, identity, and activation targets. +/// either: its image, upper, export, the network settings that its activation record names, +/// identity, and activation targets. /// /// The key comes from metadata alone: the artifacts' identities that their install metadata /// records, the class's inputs, and the capture's manifest. It never reads or digests a binary, @@ -568,15 +585,22 @@ pub struct TemplateKey { filesystem_tag: String, /// The invariant settings beyond the machine. invariants: Invariants, + /// The network, as the class lowered it to OpenVMM's arguments: empty without a NIC. + network: Vec, } impl TemplateKey { /// Version of the canonical encoding of a key, its first two bytes. + /// + /// Version 1 holds the template's network. It has not been released, so a template store that + /// an earlier build created is not supported: delete it and create a new one. There is no + /// migration. pub const VERSION: u16 = 1; /// Most bytes of a key's canonical encoding: what the largest key that a manifest of at most - /// [`MAX_MANIFEST_LEN`](super::MAX_MANIFEST_LEN) bytes can describe takes, with room to spare. - pub const MAX_LEN: usize = 256 * 1024; + /// [`MAX_MANIFEST_LEN`](super::MAX_MANIFEST_LEN) bytes can describe takes, with the most + /// arguments that a network lowers to, with room to spare. + pub const MAX_LEN: usize = 576 * 1024; /// Returns the key of the template that a capture of `class` made, whose manifest is /// `manifest`. @@ -586,8 +610,8 @@ impl TemplateKey { /// NIC, and the NIC's address and prefix, and a CPU profile that the class's request selects. /// A manifest whose machine has no processors online at boot activates all of them at boot, /// which a class whose processors are all online at boot requests. The key takes the class's - /// runtime, guest build, and invariant settings, and this crate's versions of the other - /// contracts. + /// runtime, guest build, invariant settings, and network, as the class lowers it to OpenVMM's + /// arguments, and this crate's versions of the other contracts. /// /// The key also takes the identity of the network policy that OpenVMM enforced on the NIC, /// which this check leaves to OpenVMM: OpenVMM derives it from the network arguments of the @@ -663,11 +687,11 @@ impl TemplateKey { ); } } - let attached = !class.network_arguments()?.is_empty(); + let network = class.network_arguments()?; let requested_network = class .network .as_ref() - .filter(|_| attached) + .filter(|_| !network.is_empty()) .map(|network| network.guest_network().to_owned()); // A network that `SandboxNetwork` accepts has the canonical form that this writes. let found_network = machine.nic.as_ref().map(guest_network_of); @@ -685,6 +709,7 @@ impl TemplateKey { machine: machine.clone(), filesystem_tag: MOUNT_TAG.to_owned(), invariants: class.invariants.clone(), + network, }) } @@ -773,6 +798,16 @@ impl TemplateKey { self.machine.nic.as_ref().map(guest_network_of) } + /// Returns the template's network as its class lowered it to OpenVMM's arguments, + /// [`SandboxNetwork::openvmm_arguments`]: `--net` with the guest's address, and the options + /// that enforce the policy of the template's NIC, which every restore of the template passes, + /// but `--net` and the address, which OpenVMM takes from the snapshot; none for a template + /// without a NIC. A clone's plan requires the same arguments of the network of the clone's own + /// plan, so the template serves the clones of its network policy alone. + pub fn network_arguments(&self) -> &[String] { + &self.network + } + /// Returns the SHA-256 digest of the canonical encoding of the network policy that OpenVMM /// enforces on the template's NIC, which OpenVMM computed and the manifest records, or `None` /// for a template without a NIC. @@ -864,6 +899,9 @@ impl TemplateKey { /// the network policy's mode, a text, digest, 32 bytes, whether it is required, a boolean, /// and encoding version, a `u32`; and the invariant settings, a list of names and values, /// each a text, in the order of their names. + /// 8. Network: the texts of OpenVMM's arguments to which the class lowered the network, a list, + /// empty for a template without a NIC, and otherwise starting with `--net` and the NIC's + /// IPv4 address and prefix length, `ADDRESS/PREFIX`. pub fn to_bytes(&self) -> Vec { let mut writer = Writer::default(); writer.u16(Self::VERSION); @@ -872,13 +910,16 @@ impl TemplateKey { self.contracts.write(&mut writer); write_machine(&mut writer, &self.machine, &self.filesystem_tag); self.invariants.write(&mut writer); + writer.list(&self.network, |writer, argument| writer.text(argument)); writer.finish() } /// Reads a key from its canonical encoding, as [`to_bytes`](Self::to_bytes) writes it. /// /// The bytes must be the key's one encoding, of version [`VERSION`](Self::VERSION), with no - /// value of another form than a key derived from a manifest has, and no byte left over. + /// value of another form than a key derived from a manifest has, a network that is the + /// arguments to which a network of a guest at the address of the machine's NIC lowers, if it + /// has one, and none otherwise, and no byte left over. /// /// Fails with [`ErrorCode::FormatUnsupported`](crate::ErrorCode::FormatUnsupported) for a key /// of another version, and with [`ErrorKind::Io`](crate::ErrorKind::Io) for bytes that are @@ -911,6 +952,12 @@ impl TemplateKey { let contracts = Contracts::read(reader)?; let (machine, filesystem_tag) = read_machine(reader)?; let invariants = Invariants::read(reader)?; + let network = reader.list(MAX_NETWORK_ARGUMENTS, "the network", |reader| { + Ok(reader + .text(MAX_TEXT_LEN, "an argument of the network")? + .to_owned()) + })?; + check_network(machine.nic.as_ref(), &network)?; Ok(Self { runtime, guest_build, @@ -918,6 +965,7 @@ impl TemplateKey { machine, filesystem_tag, invariants, + network, }) }; let key = read(&mut reader).map_err(malformed)?; @@ -1169,5 +1217,94 @@ fn read_machine(reader: &mut Reader<'_>) -> Result<(Machine, String), CanonicalE Ok((machine, tag)) } +/// Checks that `network`, the texts of OpenVMM's arguments of a key's network, are those of a +/// network of the NIC `nic` of the key's machine, or none for a machine without a NIC: exactly the +/// arguments to which [`SandboxNetwork::openvmm_arguments`] lowers a network of a guest at the +/// NIC's address and prefix length, which start with `--net` and that address. +/// +/// The check reads the policy back from the arguments, as `nvx-rs sandbox` reads its network +/// options, and lowers it again with its NIC attached, which renders a lowering unchanged: a +/// policy whose allow rules lower to no OpenVMM rule attaches its NIC even if it lets nothing +/// through, and reads back without them. A key whose network no policy lowers to is thus +/// malformed, rather than the network of a template that every clone's plan mismatches. +fn check_network(nic: Option<&Nic>, network: &[String]) -> Result<(), CanonicalError> { + let Some(nic) = nic else { + return if network.is_empty() { + Ok(()) + } else { + Err(CanonicalError::new( + "the network attaches a NIC that the machine does not have", + )) + }; + }; + let address = guest_network_of(nic); + match network { + [option, attached, ..] if option == "--net" && *attached == address => {} + _ => { + return Err(CanonicalError::new(format!( + "the network does not attach the machine's NIC at {address}" + ))); + } + } + let lowered = crate::net::guest_gateway(&address) + .and_then(|gateway| read_policy(&network[2..], gateway)) + .and_then(|policy| crate::host::network::attached_arguments(&policy, &address).ok()); + if lowered.as_deref() == Some(network) { + Ok(()) + } else { + Err(CanonicalError::new(format!( + "the network is not the arguments to which a network policy of a guest at {address} \ + lowers" + ))) + } +} + +/// Reads `arguments`, the options of OpenVMM that follow a network's `--net` and its value, with +/// their values, for a guest whose gateway is `gateway`, into the policy that they name, as +/// `nvx-rs sandbox` reads its network options: the rules of each action as OpenVMM reads its +/// native rules, and, without `--host-loopback`, the host-loopback access that OpenVMM keeps by +/// default. Returns `None` for an option that no lowering writes, or a value that it does not +/// take; the caller compares the policy's lowering with the arguments. +fn read_policy(arguments: &[String], gateway: Ipv4Addr) -> Option { + let options = arguments.chunks_exact(2); + if !options.remainder().is_empty() { + return None; + } + let access = |value: &str| match value { + "allow" => Some(Access::Allow), + "deny" => Some(Access::Deny), + _ => None, + }; + let mut policy = NetworkPolicy::new(Access::Deny); + policy.host_loopback = HostLoopback::Outbound; + for option in options { + let [name, value] = option else { + return None; + }; + match name.as_str() { + "--network-profile" => {} + "--network-egress" => policy.egress = access(value)?, + "--network-ingress" => policy.ingress = access(value)?, + "--host-loopback" => policy.host_loopback = access(value)?.into(), + "--network-egress-allow" => policy + .allow + .rules + .push(EgressRule::parse_native(value).ok()?), + "--network-egress-deny" => policy + .deny + .rules + .push(EgressRule::parse_native(value).ok()?), + "--host-loopback-forward" => policy + .host_loopback_forwards + .push(LoopbackForward::parse(value).ok()?), + "--network-proxy" => { + policy.proxy = Some(NetworkProxy::parse_endpoint(value, gateway).ok()?); + } + _ => return None, + } + } + Some(policy) +} + #[cfg(test)] mod tests; diff --git a/nvx-rs/src/host/template/key/tests.rs b/nvx-rs/src/host/template/key/tests.rs index 7a665b828..adaf02420 100644 --- a/nvx-rs/src/host/template/key/tests.rs +++ b/nvx-rs/src/host/template/key/tests.rs @@ -5,7 +5,10 @@ use std::collections::HashSet; use super::*; use crate::ErrorCode; -use crate::host::network::{Access, EgressRule, NetworkPolicy}; +use crate::host::network::{ + Access, Destination, EgressRule, ForwardProtocol, NetworkPolicy, NetworkProxy, Protocol, + ProxyScheme, +}; use crate::host::template::test_support::{ self as support, MIB, ManifestSpec, artifact, network_class, }; @@ -242,6 +245,18 @@ fn each_part_of_the_key_changes_it() { ("policy encoding", |_, spec| { spec.network().policy_encoding_version = 3; }), + // The network, as the class lowered it: another policy makes another key, even where the + // manifest is the same, as OpenVMM's identity of the policy would not be. + ("egress rule", |class, _| { + let policy = + NetworkPolicy::new(Access::Allow).with_deny(EgressRule::to("192.0.2.0/24")); + class.network = Some(SandboxNetwork::new("10.0.0.2/24", policy).unwrap()); + }), + ("egress default", |class, _| { + let policy = + NetworkPolicy::new(Access::Deny).with_allow(EgressRule::to("192.0.2.0/24")); + class.network = Some(SandboxNetwork::new("10.0.0.2/24", policy).unwrap()); + }), ("invariant setting", |class, _| { class.invariants = Invariants::new() .with("isolation.seccomp", "strict") @@ -363,6 +378,63 @@ fn a_key_holds_what_its_capture_made() { assert!(!key(&support::class(), &ManifestSpec::template()).has_network()); assert_eq!(made.filesystem_tag(), "microvm"); assert_eq!(made.invariants(), &Invariants::new()); + assert_eq!( + made.network_arguments(), + class.network.unwrap().openvmm_arguments().unwrap() + ); +} + +#[test] +fn a_key_holds_the_network_that_its_class_lowered() { + // A NIC's network attaches the guest at its address, then enforces its policy. + assert_eq!( + network_key().network_arguments(), + [ + "--net", + "10.0.0.2/24", + "--network-profile", + "portable", + "--network-egress", + "allow", + "--network-ingress", + "deny", + "--host-loopback", + "deny", + ] + ); + let proxy = NetworkProxy::new(3128).with_scheme(ProxyScheme::Http); + let proxied = CaptureClass { + network: Some( + SandboxNetwork::new("10.0.0.2/24", NetworkPolicy::proxy_only(proxy)).unwrap(), + ), + ..network_class() + }; + let made = key(&proxied, &ManifestSpec::with_network()); + assert_eq!(made.network_arguments()[..2], ["--net", "10.0.0.2/24"]); + assert_eq!( + made.network_arguments()[made.network_arguments().len() - 2..], + ["--network-proxy", "10.0.0.1:3128"] + ); + assert_ne!(made.identity(), network_key().identity()); + // A template without a NIC holds no network, the identity of the network that lets nothing + // through, whether its class has no network or one that attaches no NIC. + let none = key(&support::class(), &ManifestSpec::template()); + assert!(none.network_arguments().is_empty()); + let closed = CaptureClass { + network: Some( + SandboxNetwork::new("10.0.0.2/24", NetworkPolicy::new(Access::Deny)).unwrap(), + ), + ..support::class() + }; + assert_eq!(key(&closed, &ManifestSpec::template()), none); + assert_eq!( + closed.identity().unwrap(), + support::class().identity().unwrap() + ); + // Each key reads back with its network. + for made in [network_key(), made, none] { + assert_eq!(TemplateKey::from_bytes(&made.to_bytes()).unwrap(), made); + } } #[test] @@ -707,6 +779,15 @@ fn key_refusal(bytes: &[u8], code: ErrorCode) -> String { #[test] fn other_encodings_of_a_key_are_refused() { + // Every key ends with its network, a list that is empty for a template without a NIC: bytes + // without that list decode as no key, and as no key of a template without a NIC either. + let closed = key(&support::class(), &ManifestSpec::template()).to_bytes(); + let (unlisted, count) = closed.split_at(closed.len() - 4); + assert_eq!(count, [0; 4]); + assert_eq!( + key_refusal(unlisted, ErrorCode::Io), + "the template key is malformed: the network is truncated" + ); let key = network_key(); let bytes = key.to_bytes(); for version in [0u16, 2, u16::MAX] { @@ -740,6 +821,10 @@ fn other_encodings_of_a_key_are_refused() { #[test] fn keys_of_machines_that_no_manifest_describes_are_refused() { type KeyChange = fn(&mut TemplateKey); + // A network that no policy of a guest at the NIC's address lowers to, though it attaches the + // NIC: every clone's plan would mismatch it, whatever its network. + const UNLOWERED: &str = "the network is not the arguments to which a network policy of a \ + guest at 10.0.0.2/24 lowers"; let cases: &[(KeyChange, &str)] = &[ ( |key| key.machine.command_line.push_str(" quiet"), @@ -773,6 +858,75 @@ fn keys_of_machines_that_no_manifest_describes_are_refused() { |key| key.machine.cpu.revision = 0, "the machine has the invalid CPU profile vendor", ), + ( + |key| key.network.clear(), + "the network does not attach the machine's NIC at 10.0.0.2/24", + ), + ( + |key| key.network[1] = "10.0.0.3/24".to_owned(), + "the network does not attach the machine's NIC at 10.0.0.2/24", + ), + ( + |key| drop(key.network.drain(..2)), + "the network does not attach the machine's NIC at 10.0.0.2/24", + ), + // The address alone. + (|key| key.network.truncate(2), UNLOWERED), + // Ingress before egress, which no lowering orders so. + ( + |key| { + key.network.swap(4, 6); + key.network.swap(5, 7); + }, + UNLOWERED, + ), + // Another profile than OpenVMM's portable one. + (|key| key.network[3] = "strict".to_owned(), UNLOWERED), + // A rule that OpenVMM would not read. + ( + |key| { + key.network + .extend(["--network-egress-allow", "nowhere"].map(str::to_owned)); + }, + UNLOWERED, + ), + // A rule that a lowering would write in another form. + ( + |key| { + key.network + .extend(["--network-egress-deny", "192.0.2.7/24"].map(str::to_owned)); + }, + UNLOWERED, + ), + // An option without its value. + ( + |key| key.network.push("--network-egress-deny".to_owned()), + UNLOWERED, + ), + // An option that no lowering writes. + ( + |key| { + key.network + .extend(["--network-dns", "10.0.0.1"].map(str::to_owned)); + }, + UNLOWERED, + ), + // The address twice. + ( + |key| { + key.network + .extend(["--net", "10.0.0.2/24"].map(str::to_owned)) + }, + UNLOWERED, + ), + // A proxy, which a policy that allows egress cannot have. + ( + |key| { + key.network + .extend(["--network-proxy", "10.0.0.1:3128"].map(str::to_owned)); + }, + UNLOWERED, + ), ]; for (change, expected) in cases { let mut changed = network_key(); @@ -783,6 +937,13 @@ fn keys_of_machines_that_no_manifest_describes_are_refused() { "{message:?} lacks {expected:?}" ); } + // A network for a machine without a NIC. + let mut changed = key(&support::class(), &ManifestSpec::template()); + changed.network = network_key().network; + assert_eq!( + key_refusal(&changed.to_bytes(), ErrorCode::Io), + "the template key is malformed: the network attaches a NIC that the machine does not have" + ); // Invariant settings out of the order of their names, which a key never writes. let mut class = network_class(); class.invariants = Invariants::new() @@ -790,12 +951,18 @@ fn keys_of_machines_that_no_manifest_describes_are_refused() { .unwrap() .with("b", "2") .unwrap(); - let mut bytes = key(&class, &ManifestSpec::with_network()).to_bytes(); - let len = bytes.len(); + let made = key(&class, &ManifestSpec::with_network()); + let mut bytes = made.to_bytes(); + // The settings end where the network, which follows them, starts. + let mut network = Writer::default(); + network.list(made.network_arguments(), |writer, argument| { + writer.text(argument) + }); + let end = bytes.len() - network.finish().len(); let tail = [ 1, 0, 0, 0, b'b', 1, 0, 0, 0, b'2', 1, 0, 0, 0, b'a', 1, 0, 0, 0, b'1', ]; - bytes[len - tail.len()..].copy_from_slice(&tail); + bytes[end - tail.len()..end].copy_from_slice(&tail); assert_eq!( key_refusal(&bytes, ErrorCode::Io), "the template key is malformed: the invariant settings are not in the strict order of \ @@ -810,6 +977,67 @@ fn keys_of_machines_that_no_manifest_describes_are_refused() { ); } +#[test] +fn keys_read_back_the_network_of_each_policy() { + let excluded = EgressRule { + to: vec![Destination { + cidr: "192.0.2.0/24".to_owned(), + except: vec!["192.0.2.0/24".to_owned()], + }], + ports: Vec::new(), + }; + let mut open = NetworkPolicy::new(Access::Allow); + open.ingress = Access::Allow; + open.host_loopback = HostLoopback::Outbound; + let mut forwarded = NetworkPolicy::new(Access::Allow) + .with_deny(EgressRule::to("2001:db8::/32").on_port(Protocol::Udp, 53)); + forwarded.host_loopback = HostLoopback::Allow; + forwarded.host_loopback_forwards = vec![ + LoopbackForward { + protocol: ForwardProtocol::Tcp, + host_port: 8080, + guest_port: 80, + }, + LoopbackForward { + protocol: ForwardProtocol::Udp, + host_port: 5353, + guest_port: 53, + }, + ]; + let policies = [ + open, + NetworkPolicy::new(Access::Deny) + .with_allow(EgressRule::to("192.0.2.0/24").on_port(Protocol::Tcp, 443)) + .with_allow(EgressRule::to("198.51.100.7").on_port_range(Protocol::Udp, 5000, 5010)) + .with_allow(EgressRule::to("::/0").on_protocol(Protocol::Icmp)) + .with_deny(EgressRule::to("192.0.2.7")), + forwarded, + NetworkPolicy::proxy_only(NetworkProxy::new(3128).with_scheme(ProxyScheme::Https)), + // A closed policy whose allow rule excepts its whole destination, which lowers to no + // OpenVMM rule, attaches its NIC all the same, with no allow rule, with or without deny + // rules: its arguments read back as a policy that lets nothing through. + NetworkPolicy::new(Access::Deny).with_allow(excluded.clone()), + NetworkPolicy::new(Access::Deny) + .with_allow(excluded) + .with_deny(EgressRule::to("198.51.100.0/24")), + ]; + for policy in policies { + let network = SandboxNetwork::new("10.0.0.2/24", policy).unwrap(); + let lowered = network.openvmm_arguments().unwrap(); + let class = CaptureClass { + network: Some(network), + ..network_class() + }; + let made = key(&class, &ManifestSpec::with_network()); + assert_eq!(made.network_arguments(), lowered); + assert_eq!( + TemplateKey::from_bytes(&made.to_bytes()).unwrap(), + made, + "{lowered:?}" + ); + } +} + #[test] fn invariant_settings_have_one_form() { let settings = Invariants::new() @@ -1028,7 +1256,7 @@ fn the_conformance_vectors_decode_and_encode() { ); } let invalid = vectors("INVALID_KEY"); - assert_eq!(invalid.len(), 23); + assert_eq!(invalid.len(), 34); for (name, bytes, _) in invalid { let error = TemplateKey::from_bytes(&bytes).expect_err(name); assert_eq!(error.code(), ErrorCode::Io, "{name}: {error}"); diff --git a/nvx-rs/src/host/template/mod.rs b/nvx-rs/src/host/template/mod.rs index cc3df7b37..db80abf57 100644 --- a/nvx-rs/src/host/template/mod.rs +++ b/nvx-rs/src/host/template/mod.rs @@ -37,7 +37,8 @@ //! memory target against the template, and its export, if it has one, a plan of one directory, //! which the template's dormant filesystem slot binds, and refuses a request that the template //! cannot serve, such as an image of another length or block geometry than the template's -//! placeholder, or an export of several directories or of a file, before any VMM starts. +//! placeholder, a network other than the template's, which its key records, or an export of +//! several directories or of a file, before any VMM starts. //! - [`ClonePlan::launch`] launches the clone, as the launch that its lease reserves, once the //! objects of its export are still those that its plan found: OpenVMM restores the generation's //! snapshot in place with the clone's devices and export, and the clone's activation record @@ -79,7 +80,8 @@ //! - A list is its count, a `u32`, then its items in order. //! //! [`TemplateKey::from_bytes`] refuses any other encoding, and bytes left after it. The vectors in -//! `tests/vectors/template-key-v1.txt` fix version 1 of a key's encoding. +//! `tests/vectors/template-key-v1.txt` fix version 1 of a key's encoding, which holds the +//! template's network, as its class lowered it, and of a class's. mod canonical; mod clone; diff --git a/nvx-rs/tests/vectors/README.md b/nvx-rs/tests/vectors/README.md index e8c89dd8a..f46b077ad 100644 --- a/nvx-rs/tests/vectors/README.md +++ b/nvx-rs/tests/vectors/README.md @@ -12,7 +12,7 @@ yet breaks those peers. Only bytes that no codec produced catch such a change. | [`nvxc-v1.txt`](nvxc-v1.txt) | Version 1 of the control protocol: `NVXC` frames, their `EXEC`, `MAPS`, and features payloads, and `NVXS` records of NVX's host and guest | | [`nvxl-v1.txt`](nvxl-v1.txt) | Version 1 of the `NVXL` listener announcement | | [`activation-v1.txt`](activation-v1.txt) | Version 1 of the activation record of a layered root, and what Ready reports about an activation | -| [`template-key-v1.txt`](template-key-v1.txt) | Version 1 of the canonical encodings of a template's compatibility key and of a capture class, with their identities | +| [`template-key-v1.txt`](template-key-v1.txt) | Version 1 of the canonical encodings of a template's compatibility key, which holds the template's network as its capture class lowered it, and of a capture class, with their identities | | [`openvmm/`](openvmm) | OpenVMM's vectors and cases of the `NVXS` session, and the excerpts of its sources that define the kernel command-line tokens of its platform tier, unchanged | [4.4 Host-Guest Control Interface](../../../doc/design/4.4-host-guest-control-interface.md) @@ -61,12 +61,16 @@ the key that the vector's bytes decode to. its own, such as `nvxc-v2.txt` for the exec v2 of [microsoft/nvx#623](https://github.com/microsoft/nvx/issues/623), and the bytes of an earlier version that it refuses become its rejection vectors. - Version 1 has one exception: `MAPS|ROOT_SOURCE` of `nvxc-v1.txt` was the + Version 1 has two exceptions. `MAPS|ROOT_SOURCE` of `nvxc-v1.txt` was the rejection vector `INVALID_MAPS|EMPTY_SOURCE` until an empty source came to name the export's root. Only the clone of a template whose export is a directory sends one, to the template's own guest, which deploys with the host and whose build the template's key names, so the C agent of earlier - releases, which refuses it, never receives one. + releases, which refuses it, never receives one. And the keys of + `template-key-v1.txt` came to end with the template's network in place: the + key's encoding has not been released, so a template store that an earlier + build created is not supported, and is deleted and created again, since + nothing migrates it. - The bytes come from the protocol's definition, never from the code that they check, and so do the values of each vector. diff --git a/nvx-rs/tests/vectors/template-key-v1.txt b/nvx-rs/tests/vectors/template-key-v1.txt index bff4a0c2f..f00e6e20e 100644 --- a/nvx-rs/tests/vectors/template-key-v1.txt +++ b/nvx-rs/tests/vectors/template-key-v1.txt @@ -1,7 +1,8 @@ # Conformance vectors of version 1 of the canonical encodings of a template's compatibility key, # nvx::host::template::TemplateKey, and of a capture class, nvx::host::template::CaptureClass, # which the module nvx::host::template describes. README.md describes the line format and the -# rules that the vectors follow. +# rules that the vectors follow. A key ends with the template's network, as its capture class +# lowered it to OpenVMM's arguments, after the invariant settings. # # KEY|NAME|BYTES|IDENTITY # The canonical encoding of a key, and its identity: the SHA-256 digest of "nvx template key", a @@ -22,18 +23,20 @@ # ABI 1, restore packet 4, and activation contract 1. # The key of the template of a KVM microVM of 2 processors, all online at boot, and 512 MiB # of RAM, of a capacity of 2 GiB, with a distro of 1 GiB, a scratch of 64 MiB, the dormant -# filesystem slot, a console, a control console, and no NIC, on the CPU profile -# intel.icelake-sp.v1, whose digest is 32 bytes of 5a and whose effective CPUID is the bytes -# 00 to 57: the capture of tests/fixtures/template/platform-kvm. -KEY|TEMPLATE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000530100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633217f80f8858431ca75fcc7ca694ea68637e017ede02db15e18d0ed4581067858d000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001000000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0000000000|81901eda9602b4f2099c44415b7a38b035ff215b9bc50f860c8c70ca2c6f593f +# filesystem slot, a console, a control console, and no NIC, and so no network, on the CPU +# profile intel.icelake-sp.v1, whose digest is 32 bytes of 5a and whose effective CPUID is the +# bytes 00 to 57: the capture of tests/fixtures/template/platform-kvm. +KEY|TEMPLATE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000530100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633217f80f8858431ca75fcc7ca694ea68637e017ede02db15e18d0ed4581067858d000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001000000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d000000000000000000|218ead116d918d236ba226cbd9c86753927de98283a4d202ff6d69cad87ea2af # The same with a fixed NIC at 10.0.0.2/24, with its IPv6 identity, under an allow-list # policy whose digest is 32 bytes of 07, and the invariant settings isolation.seccomp=strict -# and limits.pids=512. -KEY|NETWORK|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e7069647303000000353132|f7418d9454a78af64bc5bc46e82206ccd085baf64cf7140e5ae4faf04b7c1ebe +# and limits.pids=512; its class's network allows egress, and denies ingress and host-loopback +# access: --net 10.0.0.2/24 --network-profile portable --network-egress allow +# --network-ingress deny --host-loopback deny. +KEY|NETWORK|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e70696473030000003531320a000000050000002d2d6e65740b00000031302e302e302e322f3234110000002d2d6e6574776f726b2d70726f66696c6508000000706f727461626c65100000002d2d6e6574776f726b2d65677265737305000000616c6c6f77110000002d2d6e6574776f726b2d696e67726573730400000064656e790f0000002d2d686f73742d6c6f6f706261636b0400000064656e79|061c60bcc639e2edcc7d6974446f9cbc78122cf02d0195ee4077e953ad56674e # TEMPLATE on the host profile intel.host.v1. -KEY|HOST_PROFILE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c04000000686f7374010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000530100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633217f80f8858431ca75fcc7ca694ea68637e017ede02db15e18d0ed4581067858d000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001000000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0000000000|93afa8bdde64df606707f5534c58420b92888acbbb6c8245e83006768c3ac940 -# A machine of one processor and one device, which the invalid vectors change. -KEY|MINIMAL|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000|d79a8fefc401da8568586cdc595a93a7e6c988aefbc62b03038901940211c1f1 +KEY|HOST_PROFILE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c04000000686f7374010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000530100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633217f80f8858431ca75fcc7ca694ea68637e017ede02db15e18d0ed4581067858d000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001000000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d000000000000000000|7ff9e24a8864510509c68ffaf00cac54c6a9ec391bf45f663536cd095220dea4 +# A machine of one processor and one device, and no NIC, which the invalid vectors change. +KEY|MINIMAL|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000|e7037b740fb3d00fdb4a9af7b4f0e22a7323c8a744fa697b924360e90d47816f # The class of the capture of TEMPLATE: the CPU profile auto, and 2 processors, all online at # boot. @@ -43,53 +46,75 @@ CLASS|TEMPLATE|0100470000007368613235363a616161616161616161616161616161616161616 CLASS|NETWORK|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d040000006175746f02000000020000000000002000000000000000800000000000000040000000000002000000100000000000040000000000020000000200000a000000050000002d2d6e65740b00000031302e302e302e322f3234110000002d2d6e6574776f726b2d70726f66696c6508000000706f727461626c65100000002d2d6e6574776f726b2d65677265737305000000616c6c6f77110000002d2d6e6574776f726b2d696e67726573730400000064656e790f0000002d2d686f73742d6c6f6f706261636b0400000064656e79020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e7069647303000000353132|3ed4ab3d6536faa5872354282d702ae63ed89d14bb3c12dc9102d79ea5b38c6d # MINIMAL in other versions of the encoding. -INVALID_KEY_VERSION|VERSION_0|0000470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 -INVALID_KEY_VERSION|VERSION_2|0200470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 -INVALID_KEY_VERSION|VERSION_65535|ffff470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY_VERSION|VERSION_0|0000470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 +INVALID_KEY_VERSION|VERSION_2|0200470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 +INVALID_KEY_VERSION|VERSION_65535|ffff470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # No bytes. INVALID_KEY|EMPTY| # MINIMAL without its last byte. -INVALID_KEY|TRUNCATED|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00000000 +INVALID_KEY|TRUNCATED|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000000000 # MINIMAL and a byte after it. -INVALID_KEY|TRAILING_BYTE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000 +INVALID_KEY|TRAILING_BYTE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00000000000000000000 # A command line whose digest does not match it. -INVALID_KEY|COMMAND_LINE_DIGEST|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663300000000000000000000000000000000000000000000000000000000000000000001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|COMMAND_LINE_DIGEST|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663300000000000000000000000000000000000000000000000000000000000000000001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # A backend that does not exist. -INVALID_KEY|UNKNOWN_BACKEND|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d31060000000000000001000000000000000100000000000000040000000000000001000000000000000300000078656e03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|UNKNOWN_BACKEND|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d31060000000000000001000000000000000100000000000000040000000000000001000000000000000300000078656e03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # A device range of an address space that does not exist. -INVALID_KEY|UNKNOWN_ADDRESS_SPACE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e000000000100000004000000706f7274200000000000000002000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|UNKNOWN_ADDRESS_SPACE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e000000000100000004000000706f7274200000000000000002000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # An interrupt delivery mode that is not UTF-8. -INVALID_KEY|INTERRUPT_MODE_NOT_UTF8|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000013000000656467652d7368617265642dff737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|INTERRUPT_MODE_NOT_UTF8|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000013000000656467652d7368617265642dff737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # A NIC whose presence tag is 2. -INVALID_KEY|PRESENCE_TAG_2|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0200000000 +INVALID_KEY|PRESENCE_TAG_2|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d020000000000000000 # A NIC whose policy's enforcement is 2. -INVALID_KEY|BOOLEAN_2|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c6973740707070707070707070707070707070707070707070707070707070707070707020400000000000000 +INVALID_KEY|BOOLEAN_2|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c697374070707070707070707070707070707070707070707070707070707070707070702040000000000000000000000 # Invariant settings out of the order of their names. -INVALID_KEY|UNSORTED_SETTINGS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00020000000b0000006c696d6974732e70696473030000003531321100000069736f6c6174696f6e2e736563636f6d7006000000737472696374 +INVALID_KEY|UNSORTED_SETTINGS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00020000000b0000006c696d6974732e70696473030000003531321100000069736f6c6174696f6e2e736563636f6d700600000073747269637400000000 # An invariant setting named twice. -INVALID_KEY|DUPLICATE_SETTINGS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00020000000b0000006c696d6974732e70696473030000003531320b0000006c696d6974732e7069647303000000353132 +INVALID_KEY|DUPLICATE_SETTINGS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00020000000b0000006c696d6974732e70696473030000003531320b0000006c696d6974732e706964730300000035313200000000 # An invariant setting whose name holds an uppercase letter. -INVALID_KEY|UPPERCASE_SETTING|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00010000000b0000004c696d6974732e7069647303000000353132 +INVALID_KEY|UPPERCASE_SETTING|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d00010000000b0000004c696d6974732e706964730300000035313200000000 # More APIC IDs than a microVM has processors. -INVALID_KEY|TOO_MANY_APIC_IDS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b010000000100000001000000010000000900000000000000010000000200000003000000040000000500000006000000070000000800000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|TOO_MANY_APIC_IDS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b010000000100000001000000010000000900000000000000010000000200000003000000040000000500000006000000070000000800000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # 3 processors, which a microVM cannot have. -INVALID_KEY|THREE_PROCESSORS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b010000000100000003000000010000000300000000000000010000000200000000ca9a3b0000000000e1f505000000000000000003000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|THREE_PROCESSORS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b010000000100000003000000010000000300000000000000010000000200000000ca9a3b0000000000e1f505000000000000000003000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # RAM ranges that do not hold the RAM. -INVALID_KEY|MEMORY_RANGES|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000400000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|MEMORY_RANGES|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000400000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # A machine without devices. -INVALID_KEY|NO_DEVICES|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|NO_DEVICES|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000000000001000000070000006d6963726f766d000000000000000000 # A device ID twice. -INVALID_KEY|DUPLICATE_DEVICE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000200000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000009000000706172746974696f6e05000000636c6f636b06000000766d74696d6500000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|DUPLICATE_DEVICE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000200000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000009000000706172746974696f6e05000000636c6f636b06000000766d74696d6500000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # A filesystem slot that is not the dormant slot of version 1. -INVALID_KEY|SLOT_VERSION_0|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000000000000070000006d6963726f766d0000000000 +INVALID_KEY|SLOT_VERSION_0|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000000000000070000006d6963726f766d000000000000000000 # A filesystem slot without a tag. -INVALID_KEY|EMPTY_TAG|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000000000000000000000 +INVALID_KEY|EMPTY_TAG|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e0000000000000000000000000000000000000000000100000000000000000000000000000000 # A distro whose logical block size is 256. -INVALID_KEY|DISTRO_BLOCK_SIZE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000010000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|DISTRO_BLOCK_SIZE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000010000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # An OpenVMM identity that holds a space. -INVALID_KEY|ARTIFACT_WITH_SPACE|0100470000007368613235363a20616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|ARTIFACT_WITH_SPACE|0100470000007368613235363a20616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # A CPU profile of revision 0. -INVALID_KEY|CPU_PROFILE_REVISION_0|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610000000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|CPU_PROFILE_REVISION_0|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610000000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 # An effective CPUID that is not whole entries of 44 bytes. -INVALID_KEY|CPUID_LENGTH|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112b000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 +INVALID_KEY|CPUID_LENGTH|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112b000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000000000000 +# MINIMAL with a network, for a machine without a NIC. +INVALID_KEY|NETWORK_WITHOUT_NIC|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d000000000002000000050000002d2d6e65740b00000031302e302e302e322f3234 +# NETWORK without its network. +INVALID_KEY|NIC_WITHOUT_NETWORK|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e706964730300000035313200000000 +# NETWORK with a network that attaches the guest at another address than its NIC's. +INVALID_KEY|NETWORK_OF_ANOTHER_ADDRESS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e70696473030000003531320a000000050000002d2d6e65740b00000031302e302e302e332f3234110000002d2d6e6574776f726b2d70726f66696c6508000000706f727461626c65100000002d2d6e6574776f726b2d65677265737305000000616c6c6f77110000002d2d6e6574776f726b2d696e67726573730400000064656e790f0000002d2d686f73742d6c6f6f706261636b0400000064656e79 +# NETWORK with a network that does not start with --net and the guest's address. +INVALID_KEY|NETWORK_WITHOUT_ADDRESS|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e706964730300000035313208000000110000002d2d6e6574776f726b2d70726f66696c6508000000706f727461626c65100000002d2d6e6574776f726b2d65677265737305000000616c6c6f77110000002d2d6e6574776f726b2d696e67726573730400000064656e790f0000002d2d686f73742d6c6f6f706261636b0400000064656e79 +# NETWORK with an argument of 257 bytes. +INVALID_KEY|LONG_ARGUMENT|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e70696473030000003531320a000000050000002d2d6e65740b00000031302e302e302e322f3234110000002d2d6e6574776f726b2d70726f66696c6508000000706f727461626c65100000002d2d6e6574776f726b2d65677265737305000000616c6c6f77110000002d2d6e6574776f726b2d696e67726573730400000064656e790f0000002d2d686f73742d6c6f6f706261636b010100006464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464646464 +# NETWORK with a network of --net and the guest's address alone, to which no network policy +# lowers. +INVALID_KEY|NETWORK_OF_ADDRESS_ALONE|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e706964730300000035313202000000050000002d2d6e65740b00000031302e302e302e322f3234 +# NETWORK with its --network-ingress before its --network-egress, an order in which no +# network policy lowers. +INVALID_KEY|NETWORK_OUT_OF_ORDER|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e70696473030000003531320a000000050000002d2d6e65740b00000031302e302e302e322f3234110000002d2d6e6574776f726b2d70726f66696c6508000000706f727461626c65110000002d2d6e6574776f726b2d696e67726573730400000064656e79100000002d2d6e6574776f726b2d65677265737305000000616c6c6f770f0000002d2d686f73742d6c6f6f706261636b0400000064656e79 +# TEMPLATE, NETWORK, HOST_PROFILE, and MINIMAL without their network part, the last part of +# every key, which a key of a template without a NIC holds as an empty list. +INVALID_KEY|TEMPLATE_WITHOUT_NETWORK_PART|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000530100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633217f80f8858431ca75fcc7ca694ea68637e017ede02db15e18d0ed4581067858d000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001000000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0000000000 +INVALID_KEY|NETWORK_WITHOUT_NETWORK_PART|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c0a0000006963656c616b652d7370010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000f20100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030303030303a31302076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633220766972746e65745f69703d31302e302e302e3220766972746e65745f6d61736b3d3235352e3235352e3235352e3020766972746e65745f67773d31302e302e302e3120766972746e65745f6970363d666430303a3a6130303a322f31323020766972746e65745f6777363d666430303a3a6130303a315e7d49c200c9d60e74547b549917b665501635035894c15c2d7780210f95caf0000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000c0000006e65743a6d6963726f766d300a00000076697274696f2d6e65741500000076697274696f2d6e65742d333438393636303932380b00000076697274696f2d6d6d696f01000000040000006d6d696f000000d0000000000010000000000000010a000000020000002000000001000000020000000200000000010000000100000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0108000000706f727461626c655254000000025254000000010a000002180a00000101fd00000000000000000000000a00000278fd00000000000000000000000a0000010a000000616c6c6f772d6c69737407070707070707070707070707070707070707070707070707070707070707070104000000020000001100000069736f6c6174696f6e2e736563636f6d70060000007374726963740b0000006c696d6974732e7069647303000000353132 +INVALID_KEY|HOST_PROFILE_WITHOUT_NETWORK_PART|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d05000000696e74656c04000000686f7374010000005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a58000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f50515253545556570100000001000000020000000100000002000000000000000100000000752b7d0000000000c2eb0b00000000fa000000020000000000000000000020000000000000008000000000000000080000000001000000000000000000000000000020000000000100000000000020000000000000006000000000530100006561726c79636f6e3d78653920636f6e736f6c653d68766331207265626f6f743d742070616e69633d2d31206e76785f73616e64626f783d31206e76785f636f6e6669673d307864303031303030302c3635353336206e725f637075733d32206e76785f736e617073686f745f746965723d706c6174666f726d2076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030313030303a362076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030323030303a372076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030333030303a342076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030363030303a31312076697274696f5f6d6d696f2e6465766963653d30783130303040307864303030373030303a33206e76785f636f6e74726f6c5f7474793d6876633217f80f8858431ca75fcc7ca694ea68637e017ede02db15e18d0ed4581067858d000000400000000000020000001000000000000400000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000001000000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000003000000767030040000007663707509000000706172746974696f6e00000000000000000000000000000000000000000006000000766d74696d6505000000636c6f636b06000000766d74696d65000000000000000000000000000000000000000000030000007069630300000070696303000000706963000000000200000004000000706d696f2000000000000000020000000000000004000000706d696fa00000000000000002000000000000000000000000000000000000000006000000696f6170696306000000696f6170696306000000696f617069630000000001000000040000006d6d696f0000c0fe00000000001000000000000000000000000000000000000000050000006c61706963050000006c6170696309000000706172746974696f6e0000000001000000040000006d6d696f0000e0fe00000000001000000000000000000000000000000000000000030000007069740300000070697403000000706974000000000100000004000000706d696f400000000000000004000000000000000100000000000000000000000000000000030000007274630300000072746303000000727463000000000100000004000000706d696f7000000000000000020000000000000001080000000000000000000000000000000d0000006d6963726f766d2d706f72746205000000706f7274620d0000006d6963726f766d2d706f727462000000000100000004000000706d696fe900000000000000020000000000000000000000000000000000000000100000006d6963726f766d2d73687574646f776e0800000073687574646f776e100000006d6963726f766d2d73687574646f776e000000000100000004000000706d696f0406000000000000010000000000000000000000000000000000000000180000006d6963726f766d2d736e617073686f742d7265717565737410000000736e617073686f742d72657175657374180000006d6963726f766d2d736e617073686f742d72657175657374000000000100000004000000706d696f05060000000000000100000000000000000000000000000000000000000b00000066733a6d6963726f766d300900000076697274696f2d66731300000076697274696f66732d333438393636353032340b00000076697274696f2d6d6d696f01000000040000006d6d696f001000d000000000001000000000000001060000000200000000000030030000000200000002000000000100000001000017000000636f6e736f6c653a6d6963726f766d2d76697274696f300e00000076697274696f2d636f6e736f6c651900000076697274696f2d636f6e736f6c652d333438393636393132300b00000076697274696f2d6d6d696f01000000040000006d6d696f002000d000000000001000000000000001070000000200000001000030030000000200000002000000000100000001000012000000626c6b3a73616e64626f783a64697374726f0a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393637333231360b00000076697274696f2d6d6d696f01000000040000006d6d696f003000d0000000000010000000000000010400000002000000640600300300000001000000010000000001000013000000626c6b3a73616e64626f783a736372617463680a00000076697274696f2d626c6b1500000076697274696f2d626c6b2d333438393638353530340b00000076697274696f2d6d6d696f01000000040000006d6d696f006000d0000000000010000000000000010b00000002000000440600300300000001000000010000000001000018000000636f6e736f6c653a6d6963726f766d2d636f6e74726f6c301600000076697274696f2d636f6e74726f6c2d636f6e736f6c652100000076697274696f2d636f6e74726f6c2d636f6e736f6c652d333438393638393630300b00000076697274696f2d6d6d696f01000000040000006d6d696f007000d000000000001000000000000001030000000200000001000030030000000200000002000000000100000001000001000000070000006d6963726f766d0000000000 +INVALID_KEY|MINIMAL_WITHOUT_NETWORK_PART|0100470000007368613235363a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161470000007368613235363a62626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262626262470000007368613235363a636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363630300000000000000190000006e76782d6d6963726f766d2d76322d636f6e74726f6c2d763201000000000000000d00000067756573742d6275696c642d3106000000000000000100000000000000010000000000000004000000000000000100000000000000030000006b766d03000000616d640500000067656e6f610100000011111111111111111111111111111111111111111111111111111111111111112c000000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b01000000010000000100000001000000010000000000000000ca9a3b0000000000e1f505000000000000000001000000000000000000000800000000000000080000000000000008000000000100000000000000000000000000000800000000000000000c000000636f6e736f6c653d687663308c7f813b328f96bdb26c4e97b6f5c874cbd968e8664778addc56a7c81ea55113001000000000000000020000000200000010000000000000000200000002000012000000656467652d7368617265642d737461747573000003000000000000100000000000000100000009000000706172746974696f6e09000000706172746974696f6e09000000706172746974696f6e00000000000000000000000000000000000000000001000000070000006d6963726f766d0000000000 From e19ceede707ea539e7f6ed4df7bafbd2b9a4f1b5 Mon Sep 17 00:00:00 2001 From: Enrique Saurez Date: Mon, 26 Oct 2026 11:04:36 -0700 Subject: [PATCH 2/2] runtime-adapter: start clones of network templates, in VMs `runtime-adapter-host start` takes the network of a launch, `--network FILE`, which it reads before anything else, as a launch does, and refuses with status 1 if it cannot read it, or if the plan refuses it. `clone::Request` carries it, and `Request::plan` puts it on the adapter's plan, which NVX's plan compares with the template's. The clone's record keeps the plan with its network, so `exec` gives the clone's executions the URL of the network's proxy, the one that the clone's activation record names, as it gives a launch's. In vm_clone, with templates of the networks that a capture takes, the guest at 192.0.2.2/24: - A template without a NIC serves clones without a network, and of a network that lets nothing through: no network device, no network in the record, and the image's own `/etc/resolv.conf`, which no bind holds. A clone of each network with a NIC is refused before any VMM starts, with status 8 and the record of a failure of the request, at the plan, by the evidence of invalid settings. - A template of each network with a NIC, egress allowed, with outbound host-loopback access or without, an allow rule, and a proxy, serves a clone of its network, with one network device, on Linux the VMM's arguments of the template's policy without `--net`, and a record that names the policy, the gateway's DNS server where egress is allowed, and the proxy. It refuses each other network, its own policy at another guest address, a network that lets nothing through, and none, in the same way. The templates' policies differ. - A clone of a network with egress allowed finds, at `/etc/resolv.conf`, a file of mode 0444 that names the gateway's DNS server, held by a read-only, nosuid, nodev bind after that of a generated machine ID, which a write as root cannot change, and reaches the server: a TCP connection to its DNS port opens, which the gateway's DNS proxy accepts without the host's resolver. A clone of a disk whose layer holds a regular file `etc` ends before it is ready, with status 8, the guest's status 57, and the record of a failure of the request, by the evidence of invalid settings. - The executions of a clone of a proxy-only network find the proxy's URL in `http_proxy`, `https_proxy`, `HTTP_PROXY`, and `HTTPS_PROXY`, after their own entries, and one that names its own keeps its own. - A clone of a template with a NIC maps its export below the binds of its machine ID and of its resolver configuration. The other scenarios keep templates without a NIC, so their mount tables hold no resolver configuration. Part of #846 Part of #845 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 34e6ffe3-3ebf-42db-bfca-e0ecfade6873 --- tests/runtime-adapter/README.md | 79 +- .../src/bin/runtime-adapter-host.rs | 62 +- tests/runtime-adapter/src/clone.rs | 37 +- tests/runtime-adapter/tests/clone_start.rs | 206 ++++- tests/runtime-adapter/tests/vm_clone.rs | 746 +++++++++++++++++- 5 files changed, 1063 insertions(+), 67 deletions(-) diff --git a/tests/runtime-adapter/README.md b/tests/runtime-adapter/README.md index 2ec10927e..cdbe8d48f 100644 --- a/tests/runtime-adapter/README.md +++ b/tests/runtime-adapter/README.md @@ -1387,7 +1387,14 @@ compatibility key, whose kernel command line holds the platform tier's tokens alone: neither the placeholder's identity nor a root's tokens. The template has a NIC exactly when its network lets something through: a network that denies egress, ingress, and host-loopback access, without a proxy, attaches none, as -no network does. NVX refuses a network whose policy no template takes, one that +no network does. The key holds the network as NVX lowers it, OpenVMM's +arguments of the guest's address and of its policy, none without a NIC, so each +network policy has a template of its own, which serves the +[clones](#clones) of that policy alone. The key's encoding, version 1, includes +that network and has not been released, so a template store that an earlier +build created is not supported: delete it and create a new one. There is no +migration. NVX refuses a network whose policy no +template takes, one that allows ingress or host-loopback access both ways, before any VM starts, and the command refuses a class that no capture takes, such as one of 3 processors, before it creates the store. A capture that fails leaves the store's @@ -1403,11 +1410,13 @@ library side, `clone`, holds what the command's options choose of the clone, template's placeholder, its upper, on an ext4 scratch image or in RAM, its memory target, the template's RAM unless given, the workload identity as which its executions run, its overlay mode, its scratch's journal policy, the bound -of a GPT disk's first partition, the machine ID that its executions see, and +of a GPT disk's first partition, the machine ID that its executions see, the host paths that it shares with its root, as a launch's -[shares](#shares). -`Request::plan` plans the image over the upper as a launch plans a layered -root, `Request::export` plans the export of the shares as a launch plans it, +[shares](#shares), and its [network](#networks), as a launch reads it, which +must be the template's. +`Request::plan` plans the image over the upper, with the network, as a launch +plans a layered root, `Request::export` plans the export of the shares as a +launch plans it, and `Request::clone_request` returns NVX's `CloneRequest` of both, with the bindings that the sandbox's store stages for the images, as `stage` stages them, so the start hashes nothing. The clone's activation record names the @@ -1416,12 +1425,22 @@ ID, unless the request asks for one that the guest generates once for the clone, which a read-only bind holds at the root's `/etc/machine-id` for every execution, and the guest's defaults of the other settings, unless the request names them; for a GPT disk, the bound of its first partition is 64 KiB unless -the request names one, as a launch's guest takes it by default. +the request names one, as a launch's guest takes it by default. For a template +with a NIC, the record names the network: the identity of its policy, the DNS +server with which the template's guest configured its resolver at boot, if +any, which the guest writes to a resolver file, of mode 0444, that a +read-only bind holds at the root's `/etc/resolv.conf` for every execution, +beside a generated machine ID, and the URL of the policy's proxy, if any, +which every execution of the clone finds in its environment, as an execution +of a launch does; see [Template mode](#template-mode). Without a DNS server, +the root keeps the image's own `/etc/resolv.conf`. The guest of a GPT clone rereads the disk's partition table before it assembles the root, since its kernel created the partitions of the template's placeholder. -The command first plans the export of the clone's shares, if it has any, and +The command first reads the clone's network, if given, as a launch reads it, +and refuses one that the plan refuses, then plans the export of the clone's +shares, if it has any, and refuses those that it cannot export, as a launch refuses them, then reads the generation from the store's index, and, unless the request names the clone's memory target, its compatibility key, whose RAM the target is then, before it @@ -1443,6 +1462,11 @@ time. NVX's `ClonePlan` then checks the clone against the generation from the metadata of its files alone, under the sandbox's lock, which the lease holds: +its network, which must be the one that the template's key holds, the guest's +address and the policy of the template's NIC, which every restore of the +template attaches unchanged, or, for a template without a NIC, none, or one +that lets nothing through, so that a clone of another network policy finds no +template in it, the bindings of its images, which no one else may change, the geometry of its image, which must be the placeholder's, its length included, and that of its scratch image, which must be the template's scratch's, its memory target, @@ -1455,12 +1479,15 @@ reaches the payload of a generation. A clone that the template cannot serve fails there, before any VMM starts. The command then records the clone in the sandbox's store, as `clone::CloneRecord`, in the format of a launch's [record](#layered-roots), in the mode `clone`, with the template's kernel -command line, the plan and the bindings, so that `probe` and `exec` read the -plan back, no root configuration, and the template store and the generation, so +command line, the plan, with the clone's network, and the bindings, so that +`probe` and `exec` read the plan back, and `exec` gives executions the URL of +the network's proxy, if any, as for a launch, no root configuration, and the +template store and the generation, so that a later stop finds the store whose lease it releases. Once NVX checked the export again, with `ExportPlan::verify`, OpenVMM restores the generation's snapshot in place, through NVX's supervisor, as the launch that the lease reserves, with the export's directory on the template's filesystem slot, +and the template's NIC, if it has one, under the template's network, and the restore sequence activates the clone through the adapter's clone order, `host::CloneOrder`, which sends the clone's activation record in an `Activate`, checks the guest agent's build in its `Ready`, sends @@ -1630,7 +1657,7 @@ the directory that `NVX_ARTIFACTS_DIR` names, and the guest agent's build from its record again, and releases the lease of a clone that ended, through the template store TEMPLATES, if given, in place of the one that the clone's record names. -- `start STORE --template TEMPLATES --generation G --distro FORMAT:PATH --distro-identity UUID --upper (scratch:PATH | ram) [--memory MIB] [--workload-identity UID:GID] [--overlay-mode MODE] [--scratch-journal POLICY] [--first-partition-bound BYTES] [--machine-id (image | generated)] [SHARES]` +- `start STORE --template TEMPLATES --generation G --distro FORMAT:PATH --distro-identity UUID --upper (scratch:PATH | ram) [--memory MIB] [--workload-identity UID:GID] [--overlay-mode MODE] [--scratch-journal POLICY] [--first-partition-bound BYTES] [--machine-id (image | generated)] [--network FILE] [SHARES]` starts a [clone](#clones) of the generation G of the template store TEMPLATES in the sandbox store STORE, which it creates if needed, and whose `stage` staged its images, which no one else may change: the image PATH, an @@ -1645,9 +1672,13 @@ the directory that `NVX_ARTIFACTS_DIR` names, and the guest agent's build from partition, 64 KiB by default, as a launch's guest takes it. Every execution of the clone sees the hostname `runtime-adapter`, and the machine ID that `--machine-id` chooses: the image's own, `image`, by default, or one that the - guest generates once for the clone, `generated`. SHARES, as `launch` takes + guest generates once for the clone, `generated`. The clone's VM has the + [network](#networks) that FILE holds, if given, which the start reads before + anything else, as a launch does, and which must be the template's: NVX's plan + refuses any other before any VMM starts, as [Clones](#clones) describes. + SHARES, as `launch` takes them, share host paths with the clone's root: the start refuses those that it - cannot export before anything else, and NVX's plan those that the + cannot export before anything but its network, and NVX's plan those that the template's filesystem slot cannot bind, as [Clones](#clones) describes. Once the restore sequence sent the clone's mapping table, if it has one, and started the clone's sandbox, it exchanges a `Ping` @@ -2139,11 +2170,19 @@ Windows, without a hypervisor: generation, whose image the plan refuses, and whose shares it cannot export, each with status 1 before it needs NVX's artifacts or creates the sandbox's store, and the shares before it reads the template store; +- a start whose network cannot be read, or is one that the plan refuses, with + status 1 before anything else: before its image, which does not exist, its + shares, which it cannot export, and the template store, which does not exist; - the text form of a host's time, which `RUNTIME_ADAPTER_HOST_TIME` takes, written and read back on both clocks, and the texts that are none; - a clone's record: its JSON, with the plan that `layered::LaunchRecord` reads back, the template store and the generation that a stop reads, a launch's record that is no clone's, and records that a reader refuses; +- a clone's network: the plan of a request with a proxy-only network, NVX's + request of the clone, whose plan names the proxy's URL that NVX's activation + record of the clone takes, and the clone's record, from whose plan an + execution finds that URL in each of the proxy's variables, after its own + entries; and an open network, and none, with no proxy's settings; - NVX's request of a clone, with the staged bindings, the memory target, and the guest's defaults or the request's settings, the images that the sandbox's store does not stage, which it refuses, and the export of the @@ -2499,6 +2538,8 @@ captures a template of its own, of 1 processor and 256 MiB of RAM with a capacity of 1 GiB, in a template store of its own, of a copy of NVX's Ubuntu EROFS image that a directory of the platform holds, which the clones stage as their image, or of a GPT disk of its length that the platform holds beside it, +without a NIC unless its row names a network, whose guest is at `192.0.2.2/24`, +as in the [template scenarios](#template-scenarios), and starts its clones, each in a sandbox store of its own, over a copy of the scratch template, which no one else may change either, or in RAM. The GPT disks of a template's placeholder and of the clones, which the test writes with @@ -2530,6 +2571,20 @@ directory that the starts authorize: | `clones_at_once_see_only_their_own_exports` | Four at once: one with a read-write export of its own and a generated machine ID, two over the same read-only export, over a scratch image and in RAM, and one without an export | Each with an export started with one mapping, and a record that names it by the identity of its plan, the same for the clones of one export, and on Linux, one `--mount`, read-write or read-only, as the mapping needs; each export mounted read-write, even where its mapping is read-only; below the root, the mapping, beside the bind of a generated machine ID; each clone's own directory, with its access; without an export, no export in the record, no mapping, no `--mount` on Linux, no export mounted, and nothing below the root; the `entries` probe, whose helper writes the root's machine ID, failing with `EROFS` where the generated one is bound; the host's directories with what the writable export took alone; then each stop releases its lease | | `a_start_refuses_an_export_that_a_dormant_filesystem_slot_cannot_bind_before_any_vmm_starts` | Sharing two host directories, and sharing a file alone | Status 8, with NVX's reason, and the record of a failure of the request, at the plan, without a VM, by the evidence of invalid mappings, which quarantines nothing; the lease released, and the host's directories unchanged | | `a_clone_whose_mapping_fails_ends_before_its_sandbox_starts` | Over a scratch image, sharing a host directory whose second mapping puts a directory onto a file of the image | Status 8, a `Ready`, but no start, and the record of a failure of an unknown cause, at the start, at the clone's `Ready`, by the evidence of the protocol, once the VM exited with the guest's success, or NVX terminated it, with the guest's report that the table failed after its first mapping; nothing quarantined, and the lease released, with the records; the host's directory unchanged | +| `a_template_without_a_nic_serves_clones_without_a_network` | Two at once, without a network, and with one that lets nothing through; then, once they stopped, one of each network with a NIC of the template scenarios | The first two started, with no network in their records, on Linux no argument of a network of their VMMs, no network device, and the image's own `/etc/resolv.conf`, an empty file of mode 0644, which no bind holds, and root may write; then for each of the others, status 8, with NVX's reason, and the record of a failure of the request, at the plan, without a VM, by the evidence of invalid settings, which quarantines nothing; the lease released | +| `a_template_serves_the_clones_of_its_own_network_policy_alone` | Of a template of each network with a NIC of the template scenarios: one of the template's network, then, once it stopped, one of each other network, one of the template's policy at the guest's address `192.0.2.3/24`, one of a network that lets nothing through, and one without a network | The first started, with one network device, on Linux the VMM's arguments of the template's policy, as its key holds them, without `--net`, and a record that names the policy, the gateway's DNS server for the networks with egress allowed, the proxy's URL for the proxy-only one, and no publication; from an execution, a TCP connection to the gateway at the port of each of three listeners of host loopback, which opens, and arrives at the listener, where the policy lets it through, and fails, with nothing arriving, elsewhere: the allow rule's listener alone, the proxy's alone, every one with egress and outbound host-loopback access allowed, and none with egress allowed alone; then for each of the others, status 8, with NVX's reason, and the record of a failure of the request, at the plan, without a VM, by the evidence of invalid settings, which quarantines nothing; the lease released; each template's policy differs from the others' | +| `a_clone_binds_the_resolver_of_its_policy_s_dns_server_read_only` | Of a template of a network with egress allowed, two at once, with a generated machine ID, and with the image's own; then, once they stopped, a GPT disk whose layer holds a regular file `etc`, with the image's own machine ID | Each of the first two started, with a record that names the gateway's DNS server, one network device, and at `/etc/resolv.conf`, a file of mode 0444 that names the server, held by a bind that is read-only, `nosuid`, and `nodev`, after the bind of the generated machine ID, below the root, whose file system refuses a write as root, with nothing in the upper there; and a TCP connection to the server's DNS port, which the gateway's DNS proxy accepts without the host's resolver; then status 8, since no bind can hold the resolver configuration below a file, and the record of a failure of the request, at the activation, once the VM exited, by the evidence of invalid settings, with the guest's status 57; nothing quarantined, and the lease released, with the records | +| `a_clone_s_executions_find_the_proxy_of_its_policy` | Of a template of a proxy-only network, one, with an execution as user ID 0 that runs `env`, then one that names its own `HTTPS_PROXY` | A record that names the proxy's URL, `http://192.0.2.1:PORT`, at the port of the proxy's listener, and no DNS server; the first execution with its own entry, then the URL in `http_proxy`, `https_proxy`, `HTTP_PROXY`, and `HTTPS_PROXY`; the second with exactly its own environment; one network device, and the image's own `/etc/resolv.conf`, which no bind holds | +| `a_clone_of_a_template_with_a_nic_maps_its_export_beside_its_resolver` | Of a template of a network with egress allowed, one with a generated machine ID, sharing a host directory read-write | Started, with one mapping, and a record that names the export and the gateway's DNS server; on Linux, the VMM's one `--mount`, read-write, and its arguments of the template's policy; below the root, the binds of the machine ID and of the resolver configuration, then the export's mapping; the export's directory, and a write through it, which the host's directory holds after the stop | + +Every network that the scenarios give a template is one that a template takes: +a network that lets nothing through, egress allowed, with outbound +host-loopback access or without, one rule that allows TCP to the gateway at the +port of a listener of host loopback, or a proxy at the port of another. The +tests bind those listeners, and a third, which no network names, on host IPv4 +loopback, at ports that the host chooses, and hold them until they end. A +clone's start names its network by a file that the test writes in the +template's directory. A test that fails keeps its template's directory, with the template store and the platform's image, as long as it keeps the directory of a clone that leases diff --git a/tests/runtime-adapter/src/bin/runtime-adapter-host.rs b/tests/runtime-adapter/src/bin/runtime-adapter-host.rs index 235b51309..aa73d6b7a 100644 --- a/tests/runtime-adapter/src/bin/runtime-adapter-host.rs +++ b/tests/runtime-adapter/src/bin/runtime-adapter-host.rs @@ -98,19 +98,24 @@ //! - `runtime-adapter-host start STORE --template TEMPLATES --generation G --distro FORMAT:PATH //! --distro-identity UUID --upper (scratch:PATH | ram) [--memory MIB] [--workload-identity //! UID:GID] [--overlay-mode MODE] [--scratch-journal POLICY] [--first-partition-bound BYTES] -//! [--machine-id (image | generated)] [SHARES]` starts a clone of the generation G of the -//! template store TEMPLATES, an `nvx::host::template::Store`, in the sandbox store STORE, which -//! it creates if needed; see `runtime_adapter::clone`. SHARES, as `launch` takes them, share +//! [--machine-id (image | generated)] [--network FILE] [SHARES]` starts a clone of the +//! generation G of the template store TEMPLATES, an `nvx::host::template::Store`, in the sandbox +//! store STORE, which it creates if needed; see `runtime_adapter::clone`. The clone's VM has the +//! network of the file FILE, if given, which the command reads first, as `launch` reads its +//! network: it must be the template's, the guest's address and the policy of the template's NIC, +//! which every restore of the template attaches, or for a template without a NIC none, or one +//! that lets nothing through. SHARES, as `launch` takes them, share //! host paths with the clone's root: the command plans their export as a launch does, with -//! NVX's `filesystem::plan`, and refuses shares that it cannot export before anything else. It -//! then reads the generation from the store's index, and, unless MIB mebibytes are given, its -//! compatibility key, whose RAM is then the clone's memory target, before it needs NVX's -//! artifacts. A key that cannot be read is left to NVX's plan, which reads it again, and +//! NVX's `filesystem::plan`, and refuses shares that it cannot export before anything but its +//! network. It then reads the generation from the store's index, and, unless MIB mebibytes are +//! given, its compatibility key, whose RAM is then the clone's memory target, before it needs +//! NVX's artifacts. A key that cannot be read is left to NVX's plan, which reads it again, and //! attributes the failure, to the generation or to the host, as it does for every clone. The //! store then leases the generation to the sandbox, at the host's time, with `Store::acquire`, //! which refuses a generation that a tombstone quarantines, or that is not eligible then, and //! NVX's `ClonePlan` checks the clone against the generation, from the metadata of its files -//! alone: its image, the raw file PATH, an EROFS filesystem, `erofs`, or a GPT disk, `gpt`, of +//! alone: its network, which must be the one that the template's key records, its image, the +//! raw file PATH, an EROFS filesystem, `erofs`, or a GPT disk, `gpt`, of //! which the guest expects the identity UUID, of the length of the template's placeholder, //! whatever the placeholder's format, its upper, the ext4 scratch image PATH, of the geometry of //! the template's scratch, or RAM, with the bindings that STORE stages for the images, as @@ -128,8 +133,13 @@ //! identity UID:GID, if given, as which every execution runs, whose account the guest checks in //! the clone's root before it is ready, the overlay mode MODE and the scratch's journal policy //! POLICY, as a launch takes them, for a GPT disk, the bound BYTES of its first partition, 64 -//! KiB unless given, as a launch's guest takes it by default, and the export, by the identity of -//! its plan, with the number of its mappings. Every execution of the clone sees the hostname +//! KiB unless given, as a launch's guest takes it by default, the export, by the identity of +//! its plan, with the number of its mappings, and for a template with a NIC its network: the +//! identity of its policy, the DNS server with which the template's guest configured its +//! resolver at boot, if any, whose address the clone's guest writes to a resolver file that it +//! binds read-only over the root's `/etc/resolv.conf`, and the URL of the policy's proxy, if +//! any, which every execution then finds in its environment, as a launch's executions do. Every +//! execution of the clone sees the hostname //! `runtime-adapter`, and the machine ID that `--machine-id` chooses: the image's own, `image`, //! by default, or one that the guest generates once for the clone, `generated`, which a //! read-only bind holds at `/etc/machine-id`. The guest refuses a first partition larger than @@ -431,7 +441,8 @@ const USAGE: &str = concat!( " [--memory MIB]\n", " [--workload-identity UID:GID] [--overlay-mode MODE]", " [--scratch-journal POLICY]\n", - " [--first-partition-bound BYTES] [--machine-id (image | generated)]\n", + " [--first-partition-bound BYTES] [--machine-id (image | generated)]", + " [--network FILE]\n", " [--share HOST:TARGET[:ro]... [--deny PATH]... [--reserved TARGET]...", " [--share-root DIR]...]\n", " runtime-adapter-host probe STORE PROBE... [--guest-build BUILD]\n", @@ -654,8 +665,11 @@ struct CloneOptions { templates: PathBuf, /// The generation of the template store that the clone leases. generation: StoreGeneration, - /// The clone's image, upper, memory target, and settings. + /// The clone's image, upper, memory target, and settings, without its network. request: runtime_adapter::clone::Request, + /// The file of the clone's network, if it has one, which the start reads first, as a launch + /// reads its network. + network: Option, } /// The options of a command. @@ -958,7 +972,9 @@ fn parse(arguments: Vec) -> Result { first_partition_bound: options.first_partition_bound, machine_id: options.machine_id.unwrap_or(MachineIdMode::Image), sharing: options.sharing, + network: None, }, + network: options.network, }), time: host_time_from_env()?, } @@ -1094,7 +1110,7 @@ fn parse_option( ("launch" | "start", "--deny") => options.sharing.add_denied(value), ("launch" | "start", "--reserved") => options.sharing.add_reserved(text(value)?), ("launch" | "start", "--share-root") => options.sharing.add_root(value), - ("launch" | "create", "--network") if options.network.is_none() => { + ("launch" | "create" | "start", "--network") if options.network.is_none() => { options.network = Some(PathBuf::from(value)); } ("create", "--cpu-profile") if options.cpu_profile.is_none() => { @@ -1785,11 +1801,23 @@ fn start( clone: &CloneOptions, time: Option, ) -> Result { + // A network that the plan refuses fails the start before anything else, as it fails a launch. + // NVX's plan of the clone then requires the template's network of it. + let network = clone + .network + .as_deref() + .map(read_network) + .transpose() + .map_err(|error| describe(&error))?; + let request = runtime_adapter::clone::Request { + network, + ..clone.request.clone() + }; // A request that the adapter's plan refuses, shares that it cannot export, and a generation // that the template store does not hold, fail the start before it needs NVX's artifacts or // the sandbox's store. - let plan = clone.request.plan().map_err(|error| describe(&error))?; - let export = clone.request.export().map_err(|error| describe(&error))?; + let plan = request.plan().map_err(|error| describe(&error))?; + let export = request.export().map_err(|error| describe(&error))?; let templates = Store::open(&clone.templates).map_err(|error| describe(&error))?; let generation = templates .index() @@ -1838,7 +1866,7 @@ fn start( } let clone = CloneLaunch { templates: &templates, - request: &clone.request, + request: &request, plan, export, memory, @@ -1873,7 +1901,7 @@ struct CloneLaunch<'a> { templates: &'a Store, /// The clone, as the command's options give it. request: &'a runtime_adapter::clone::Request, - /// The adapter's plan of the clone's image over its upper. + /// The adapter's plan of the clone's image over its upper, with its network. plan: nvx::host::sandbox::SandboxPlan, /// The export of the host paths that the clone shares with its root, if any. export: Option, diff --git a/tests/runtime-adapter/src/clone.rs b/tests/runtime-adapter/src/clone.rs index 0587fdd1d..06f1c2b82 100644 --- a/tests/runtime-adapter/src/clone.rs +++ b/tests/runtime-adapter/src/clone.rs @@ -5,16 +5,17 @@ //! layer or a GPT disk of the length of the template's placeholder, its upper, on an ext4 scratch //! image or in RAM, its memory target, the workload identity as which its executions run, its //! overlay mode, its scratch's journal policy, the bound of a GPT disk's first partition, the -//! machine ID that its executions see, the image's own or one that its guest generates, and the -//! host paths that it shares with its root, as a launch shares them, `sharing::HostFsSharing`. -//! [`Request::plan`] plans the image over the upper as a launch plans a layered root, -//! [`Request::export`] plans the export of the shares as a launch plans it, and +//! machine ID that its executions see, the image's own or one that its guest generates, the host +//! paths that it shares with its root, as a launch shares them, `sharing::HostFsSharing`, and its +//! network, as a launch reads it, `layered::read_network`, which must be the template's. +//! [`Request::plan`] plans the image over the upper, with the network, as a launch plans a layered +//! root, [`Request::export`] plans the export of the shares as a launch plans it, and //! [`Request::clone_request`] returns NVX's `nvx::host::template::CloneRequest` of both, with the //! bindings that the sandbox's store stages for its images, as `staged::Staged` records them: //! staging hashes, and a start never does. NVX's `ClonePlan` then checks the request against the -//! leased generation before any VMM starts, from the metadata of the clone's files alone, and -//! takes only an export of one directory, which the clone's restore binds to the template's -//! dormant filesystem slot. +//! leased generation before any VMM starts, from the metadata of the clone's files alone, takes +//! only the template's network, as the template's key records it, and only an export of one +//! directory, which the clone's restore binds to the template's dormant filesystem slot. //! //! A clone's [record](CloneRecord) names the template store and the generation that the clone //! leases, beside the plan and the bindings, as the record of a launch names what it launched, so @@ -36,8 +37,8 @@ use nvx::activation::{ }; use nvx::host::filesystem::ExportPlan; use nvx::host::process::BootId; -use nvx::host::sandbox::SandboxPlan; use nvx::host::sandbox::distro::DISTRO_POLICY_REVISION; +use nvx::host::sandbox::{SandboxNetwork, SandboxPlan}; use nvx::host::template::{CloneRequest, HostClock, HostTime}; use nvx::protocol::root::ImageFormat; use nvx::uuid::Uuid; @@ -92,12 +93,18 @@ pub struct Request { pub machine_id: MachineIdMode, /// The host paths that the clone shares with its root, as a launch shares them, if any. pub sharing: HostFsSharing, + /// The network of the clone's VM, as a launch reads it, `layered::read_network`, if it has + /// one: the template's network, the guest's address and the policy of the template's NIC, which + /// every restore of the template attaches, or for a template without a NIC none, or one that + /// lets nothing through. + pub network: Option, } impl Request { - /// Returns the adapter's plan of the clone's image over its upper, as a launch plans a layered - /// root, with the paths absolute and normalized, checked against the host with - /// `SandboxPlan::validated`. + /// Returns the adapter's plan of the clone's image over its upper, with its network, as a + /// launch plans a layered root, with the paths absolute and normalized, checked against the + /// host with `SandboxPlan::validated`. The clone's record keeps the plan, so that an execution + /// of the clone finds the URL of its network's proxy, if any, as a launch's does. /// /// Fails as a launch plans its root: with [`ErrorKind::Unsupported`](nvx::ErrorKind::Unsupported) /// for a path that is not Unicode, and otherwise as `SandboxPlan::validated` does, such as for @@ -109,6 +116,7 @@ impl Request { self.identity, self.scratch.as_deref(), ) + .map(|plan| plan.with_network(self.network.clone())) } /// Plans the export of the host paths that the clone shares with its root, as a launch plans @@ -200,8 +208,9 @@ impl Request { /// ``` /// /// The kernel command line is the template's, which the clone restores, the plan and the bindings -/// those of the clone's image and upper, as a layered launch records them, so that -/// `layered::LaunchRecord::read_plan` reads the plan back, and a clone sends no root +/// those of the clone's image and upper, with its network, as a layered launch records them, so +/// that `layered::LaunchRecord::read_plan` reads the plan back, and an execution of the clone finds +/// the URL of its network's proxy, if any, as a launch's does, and a clone sends no root /// configuration: its activation record, which NVX keeps in the sandbox, holds its settings. /// `template` names the template store, by its absolute path, and the generation that the clone /// leases. @@ -213,7 +222,7 @@ pub struct CloneRecord<'a> { pub generation: StoreGeneration, /// The template's kernel command line. pub kernel_command_line: &'a str, - /// The plan of the clone's image over its upper. + /// The plan of the clone's image over its upper, with its network. pub plan: &'a SandboxPlan, /// The bindings that the clone's plan checked. pub bindings: &'a Bindings, diff --git a/tests/runtime-adapter/tests/clone_start.rs b/tests/runtime-adapter/tests/clone_start.rs index fe2556802..34f02872f 100644 --- a/tests/runtime-adapter/tests/clone_start.rs +++ b/tests/runtime-adapter/tests/clone_start.rs @@ -1,26 +1,34 @@ //! The host program's `start` refuses options that do not make a start, and a clock fixture that is -//! not a host's time, as usage errors, and shares that it cannot export, a generation that the -//! template store does not hold, or a template store that does not exist, before it needs NVX's -//! artifacts or creates the sandbox's store. A clone's record names its template store and its -//! generation, which a stop reads back, beside the plan that the other commands read, a clone's -//! request carries the export of its shares, and a host's time keeps its text form, the form of -//! the clock fixture. The tests need no hypervisor. +//! not a host's time, as usage errors, and a network that the plan refuses, shares that it cannot +//! export, a generation that the template store does not hold, or a template store that does not +//! exist, before it needs NVX's artifacts or creates the sandbox's store. A clone's record names its +//! template store and its generation, which a stop reads back, beside the plan that the other +//! commands read, with the clone's network, whose proxy an execution of the clone then finds at +//! the URL that NVX's activation record names, a clone's request carries the export of its shares, +//! and a host's time keeps its text form, the form of the clock fixture. The tests need no +//! hypervisor. #![cfg(feature = "host")] use std::fs; use std::num::NonZeroU64; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; +use std::time::Duration; use nvx::activation::{MachineIdMode, StoreGeneration}; +use nvx::exec::{Key, Limits, Timers, Window}; use nvx::host::artifacts::Artifacts; +use nvx::host::sandbox::SandboxNetwork; use nvx::host::template::{HostClock, HostTime, Store}; use nvx::protocol::root::ImageFormat; use nvx::uuid::Uuid; use runtime_adapter::clone::{ CLONE_MODE, CloneRecord, HOST_TIME_VARIABLE, Request, host_time_text, parse_host_time, }; -use runtime_adapter::layered::{Bindings, LaunchRecord, RECORD_FORMAT, RECORD_NAME}; +use runtime_adapter::exec::Start; +use runtime_adapter::layered::{ + Bindings, LaunchRecord, PROXY_VARIABLES, RECORD_FORMAT, RECORD_NAME, read_network, with_proxy, +}; use runtime_adapter::root::DEFAULT_FIRST_PARTITION_BOUND; use runtime_adapter::sharing::{HostFsSharing, Share}; use runtime_adapter::staged::Staged; @@ -154,6 +162,17 @@ fn the_host_program_refuses_options_that_do_not_make_a_start() { with(&["--upper", "ram", "--template", "other"]), "unexpected option \"--template\" of start", ), + ( + with(&[ + "--upper", + "ram", + "--network", + "network.json", + "--network", + "other.json", + ]), + "unexpected option \"--network\" of start", + ), ( with(&["--upper", "ram", "extra"]), "unexpected argument \"extra\" of start", @@ -210,11 +229,10 @@ fn the_host_program_refuses_options_that_do_not_make_a_start() { ), ]; // Each option that a start does not take. - let others: [(&str, &str); 6] = [ + let others: [(&str, &str); 5] = [ ("--guest-agent", "agent"), ("--hypervisor", "whp"), ("--runtime-dir", "/run/a"), - ("--network", "network.json"), ("--cpu-profile", "auto"), ("--memory-capacity", "512"), ]; @@ -398,6 +416,7 @@ fn a_clone_s_record_names_its_template_store_and_generation_beside_its_plan() { first_partition_bound: None, machine_id: MachineIdMode::Image, sharing: HostFsSharing::default(), + network: None, }; let plan = request.plan().unwrap(); let staged = Staged::stage(&distro, ImageFormat::Erofs, identity(), Some(&scratch)).unwrap(); @@ -488,6 +507,7 @@ fn a_clone_s_request_takes_the_staged_bindings_and_the_guest_s_defaults() { first_partition_bound: None, machine_id: MachineIdMode::Image, sharing: HostFsSharing::default(), + network: None, }; let plan = request.plan().unwrap(); let staged = Staged::stage(&distro, ImageFormat::Erofs, identity(), Some(&scratch)).unwrap(); @@ -694,3 +714,171 @@ fn a_start_refuses_shares_that_it_cannot_export_before_anything_else() { assert!(!templates.exists()); } } + +/// Returns the serde form of a network of a guest at `192.0.2.2/24` whose one way out is a proxy +/// at port 3128 of host loopback, with the scheme `http`. +fn proxied() -> Value { + json!({ + "guestNetwork": "192.0.2.2/24", + "egress": "deny", + "allow": {"name": "egress.allow", "rules": []}, + "deny": {"name": "egress.deny", "rules": []}, + "ingress": "deny", + "hostLoopback": "deny", + "hostLoopbackForwards": [], + "proxy": {"port": 3128, "scheme": "http"}, + }) +} + +/// Writes the network `form` at `path`, and reads it back as a start reads its network. +fn written_network(path: &Path, form: &Value) -> SandboxNetwork { + fs::write(path, form.to_string()).unwrap(); + read_network(path).unwrap() +} + +/// Returns the start of an execution of `/usr/bin/env` with the environment `A=1`. +fn printing() -> Start { + let limits = Limits::new(16 * 1024, Window::frames(4), Window::frames(8)).unwrap(); + let timers = Timers::new(Duration::from_secs(1), Duration::from_secs(5)); + Start::new(Key::new(1, 2), limits, timers, ["/usr/bin/env"]).with_environment(["A=1"]) +} + +#[test] +fn a_clone_s_plan_request_and_record_carry_its_network() { + let directory = directory("clone-network"); + let distro = image(directory.join("distro.erofs"), 4096); + let network = written_network(&directory.join("proxied.json"), &proxied()); + let request = Request { + distro: distro.clone(), + format: ImageFormat::Erofs, + identity: identity(), + scratch: None, + memory: None, + workload_identity: None, + overlay_mode: None, + scratch_journal: None, + first_partition_bound: None, + machine_id: MachineIdMode::Image, + sharing: HostFsSharing::default(), + network: Some(network.clone()), + }; + + // The adapter's plan has the network, and NVX's request of the clone has the plan, whose + // network NVX's plan compares with the template's, and whose proxy's URL NVX's activation + // record of the clone names. + let plan = request.plan().unwrap(); + assert_eq!(plan.network(), Some(&network)); + let url = plan.proxy_url().expect("the network has a proxy"); + assert_eq!(url, "http://192.0.2.1:3128"); + let staged = Staged::stage(&distro, ImageFormat::Erofs, identity(), None).unwrap(); + let bindings = staged.bindings(&plan); + let clone = request + .clone_request(plan.clone(), None, &bindings, 512 << 20) + .unwrap(); + assert_eq!(clone.adapter, plan); + assert_eq!( + clone.adapter.network().and_then(SandboxNetwork::proxy_url), + Some(url.clone()) + ); + + // The clone's record keeps the plan, with its network, so an execution of the clone finds the + // proxy's URL that the activation record names in each of the proxy's variables, after its + // own entries, as an execution of a launch does. + let sandbox = directory.join("store"); + fs::create_dir(&sandbox).unwrap(); + let templates = directory.join("templates"); + let record = CloneRecord { + template: &templates, + generation: StoreGeneration::new(NonZeroU64::new(1).unwrap()), + kernel_command_line: "nvx_sandbox=1 nvx_snapshot_tier=platform", + plan: &plan, + bindings: &bindings, + }; + record.write(&sandbox).unwrap(); + let read = LaunchRecord::read_plan(&sandbox).unwrap().unwrap(); + assert_eq!(read, plan); + let expected = std::iter::once("A=1".to_owned()) + .chain(PROXY_VARIABLES.map(|variable| format!("{variable}={url}"))) + .map(String::into_bytes) + .collect::>(); + assert_eq!(with_proxy(printing(), &read).environment, expected); + + // A network without a proxy, and no network, give an execution no proxy's settings. + let mut open = proxied(); + open["egress"] = json!("allow"); + open["proxy"] = Value::Null; + let open = Request { + network: Some(written_network(&directory.join("open.json"), &open)), + ..request.clone() + }; + let none = Request { + network: None, + ..request + }; + for request in [open, none] { + let plan = request.plan().unwrap(); + assert_eq!(plan.network(), request.network.as_ref()); + assert_eq!(plan.proxy_url(), None); + assert_eq!(with_proxy(printing(), &plan), printing()); + } +} + +#[test] +fn a_start_refuses_a_network_that_the_plan_refuses_before_anything_else() { + // The start reads its network before it plans its image, which does not exist, or the export + // of its shares, which it cannot export, reads the template store, which does not exist, or + // needs NVX's artifacts, which the commands do not name, and before it creates the sandbox's + // store. + let directory = directory("start-unnetworked"); + let templates = directory.join("templates"); + let store = directory.join("store"); + let distro = format!("erofs:{}", directory.join("missing.erofs").display()); + let share = format!("{}:/srv/data", directory.join("missing").display()); + let missing = directory.join("missing.json"); + let refused = directory.join("refused.json"); + let mut form = proxied(); + form["egress"] = json!("allow"); + fs::write(&refused, form.to_string()).unwrap(); + let cases = [ + ( + &missing, + format!("cannot read the network {}", missing.display()), + ), + ( + &refused, + format!( + "the network {} is refused: a network proxy needs egress denied by default", + refused.display() + ), + ), + ]; + for (network, problem) in cases { + let arguments = [ + "start", + store.to_str().unwrap(), + "--template", + templates.to_str().unwrap(), + "--generation", + "1", + "--distro", + &distro, + "--distro-identity", + IDENTITY, + "--upper", + "ram", + "--share", + &share, + "--network", + network.to_str().unwrap(), + ]; + let output = host(&arguments, None); + assert_eq!(output.status.code(), Some(1), "{arguments:?}: {output:?}"); + let stderr = String::from_utf8_lossy(&output.stderr); + assert!(stderr.contains(&problem), "{arguments:?}: {stderr}"); + for other in ["template store", "--share", "missing.erofs", "usage:"] { + assert!(!stderr.contains(other), "{other}: {stderr}"); + } + assert!(!store.exists(), "the start created the sandbox's store"); + assert!(!templates.exists()); + } +} diff --git a/tests/runtime-adapter/tests/vm_clone.rs b/tests/runtime-adapter/tests/vm_clone.rs index d3e0cee85..c90010283 100644 --- a/tests/runtime-adapter/tests/vm_clone.rs +++ b/tests/runtime-adapter/tests/vm_clone.rs @@ -5,10 +5,14 @@ //! //! Each scenario captures a [`Template`] of its own, with 256 MiB of RAM, of a capacity of //! 1 GiB, in a template store of its own, as `vm_template` does, of the platform's copy of the -//! fixtures' Ubuntu EROFS image, or of a GPT [`Disk`] of the image's length, and starts its +//! fixtures' Ubuntu EROFS image, or of a GPT [`Disk`] of the image's length, without a NIC unless +//! the scenario gives it a [`Network`], with the guest at `192.0.2.2/24`, and starts its //! clones, each in a sandbox store of its own, which stages the clone's images, as a launch's //! does: that copy, or a GPT disk, and for a clone over a scratch image, a copy of the scratch -//! template, which, as NVX requires of a clone's images, no one else may change either. +//! template, which, as NVX requires of a clone's images, no one else may change either. The +//! scenarios of exports, as the others but those of networks, capture templates without a NIC, +//! whose clones bind no resolver configuration, so the mount tables that they check hold no +//! `/etc/resolv.conf`. //! //! - One generation serves clones over a scratch image and in RAM, at once and in turn, at each //! memory target from the template's RAM to its capacity, which the guest has online. The store @@ -87,6 +91,32 @@ //! disk to its end shows the guest's statistics count. //! - A clone's time settles after it is ready, with no violation, after the downtime that the //! host's monotonic clock measured. +//! - A template without a NIC serves clones without a network, and of a network that lets nothing +//! through, which attaches no NIC either: neither has a network device, nor a network in its +//! record, and each keeps the image's own `/etc/resolv.conf`, which no bind holds. NVX's plan +//! refuses a clone of a network with a NIC there before any VMM starts. +//! - A template of each network with a NIC that a template takes serves the clones of its own +//! network alone: their restores attach the template's NIC under its policy, unchanged, which +//! lets through what the policy allows alone, and their records name the policy, the DNS server +//! with which the template's guest configured its resolver at boot, where the policy lets the +//! guest reach the gateway's, and the proxy, if any. Of the listeners of host loopback that the +//! tests bind, a clone reaches at its gateway the allow rule's alone, the proxy's alone, every +//! one with egress and outbound host-loopback access allowed, and none without host-loopback +//! access. NVX's plan refuses, before any VMM starts, a clone of another network, of the +//! template's policy at another address of the guest, of a network that lets nothing through, +//! and one without a network. Each template's key holds a policy of its own. +//! - A clone of a network that lets the guest reach the gateway's DNS server finds a resolver +//! file that names it, of mode 0444, which a read-only bind holds at `/etc/resolv.conf`, after +//! the bind of a generated machine ID, as mount tables list them, and which no write changes, +//! and reaches the server through the template's NIC: a TCP connection to its DNS port opens, +//! which the gateway's DNS proxy accepts itself. A clone whose resolver configuration cannot be +//! bound, since its image holds a regular file `etc`, ends before it is ready, with the status +//! of its network settings. +//! - The executions of a clone of a proxy-only network find the URL of its proxy, which its record +//! names, in their environment, as a launch's executions do, and the clone keeps the image's own +//! `/etc/resolv.conf`. +//! - A clone of a template with a NIC maps its export once it is ready, below the binds of its +//! resolver configuration and of a generated machine ID. //! //! The tests boot VMs, so they are ignored. They read what the `common` module lists, and take //! the template's image and the scratch template from its fixtures. @@ -104,13 +134,16 @@ use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io; use std::mem; +use std::net::{IpAddr, Ipv4Addr, TcpListener}; use std::num::NonZeroU64; use std::path::{Path, PathBuf}; +use std::sync::LazyLock; use std::thread; use std::time::{Duration, Instant, SystemTime}; use nvx::activation::{ - ActivationRecord, Configuration, ExportKind, MachineIdMode, ReadyActivation, StoreGeneration, + ActivationRecord, Configuration, ExportKind, MachineIdMode, Publication, ReadyActivation, + StoreGeneration, }; use nvx::exec::{Key, Limits, Timers, Window}; use nvx::host::artifacts::Artifacts; @@ -118,6 +151,7 @@ use nvx::host::artifacts::Artifacts; use nvx::host::filesystem::GUEST_EXPORT; use nvx::host::platform::Transport; use nvx::host::process::{BootId, Process}; +use nvx::host::sandbox::SandboxNetwork; use nvx::host::store::{CallerFiles, LOG_NAME, SandboxStore}; use nvx::host::template::{ CAPTURE_RECORD_NAME, CloneControl, ClonePlan, CloneRecords, Evidence, GENERATIONS_NAME, @@ -135,10 +169,12 @@ use runtime_adapter::exec::{HostMessage, Start}; use runtime_adapter::frame::Message; use runtime_adapter::hook::{Action, STEP_HOOK, Step, StepHook}; use runtime_adapter::host::Client; +use runtime_adapter::layered::PROXY_VARIABLES; use runtime_adapter::root::DEFAULT_RUNTIME; use runtime_adapter::runtime::Runtime; use runtime_adapter::sharing::HostFsSharing; use runtime_adapter::staged::Staged; +use serde_json::{Value, json}; use common::gpt::{self, Contents, Layout, Partition, hexadecimal, small_layer}; use common::{Fixtures, Printed, Sandbox}; @@ -251,6 +287,50 @@ done /// The `map` probe of the clones that share one host directory at `/srv/data`: the directory, and /// its file `marker`. const MAP_DATA: &str = "map data=srv/data marker=srv/data/marker"; +/// The guest's address and prefix in the networks of the scenarios' templates and clones, in a +/// range reserved for documentation, which no host's own address shares, as `vm_template` gives +/// it. +const GUEST_NETWORK: &str = "192.0.2.2/24"; +/// Another address of the guest in the same network, at which no template has its NIC. +const OTHER_GUEST_NETWORK: &str = "192.0.2.3/24"; +/// The gateway of the scenarios' networks, the first address of the guest's, at which the guest +/// reaches the DNS server that OpenVMM serves, and host loopback. +const GATEWAY: &str = "192.0.2.1"; +/// The host's side of the scenarios' networks, which the tests bind the first time that they name +/// one of its ports, and hold until they end. +static HOST_SIDE: LazyLock = LazyLock::new(HostSide::bind); +/// How long the host waits at a service of its side for a connection that a clone opened there, +/// where the clone's network lets it through. +const ARRIVAL: Duration = Duration::from_secs(10); +/// How long the host waits at a service of its side for a connection where the clone's network +/// must not let it through. +const NEGATIVE_OBSERVATION: Duration = Duration::from_millis(250); +/// The proxy's settings of an execution that names its own, which it keeps. +const OWN_PROXY: &str = "HTTPS_PROXY=http://proxy.example:8080"; +/// The `map` probe of a clone's resolver configuration: what the root's `/etc/resolv.conf` shows. +const MAP_RESOLVER: &str = "map resolver=etc/resolv.conf"; +/// The program of the executions that show what a clone has of its network, `/bin/sh -c +/// NETWORK_VIEW sh`, which prints, a line each: the number of the guest's network devices besides +/// loopback, as `/sys/class/net` lists them, `devices N`, and the mode and the type of the root's +/// `/etc/resolv.conf`, as `stat` prints them, `resolver MODE TYPE`. +const NETWORK_VIEW: &str = "echo \"devices $(ls /sys/class/net | grep -cvx lo)\"; \ + echo \"resolver $(stat -c '%a %F' /etc/resolv.conf)\""; +/// The program of the executions that try the DNS server that a clone's resolver configuration +/// names, `/bin/sh -c DNS_REACH sh`, which prints, a line each: the server, `server ADDRESS`, and +/// `dns 0` once a TCP connection to the server's port 53, which it tries with `nc` for at most 2 +/// seconds, opened, or `dns 1` once it failed. The gateway's DNS proxy accepts that connection +/// itself, before any query of the guest reaches the host's resolver, so whether it opens depends +/// on neither that resolver nor its upstream servers. +const DNS_REACH: &str = "server=$(sed -n 's/^nameserver //p' /etc/resolv.conf); \ + echo \"server $server\"; nc -z -w 2 \"$server\" 53 /dev/null 2>&1; \ + echo \"dns $?\""; +/// The program of the executions that try the services of the host's side of a clone's network, +/// `/bin/sh -c "set -- GATEWAY TARGET...; REACH"`, each target `NAME:PORT`, which tries a TCP +/// connection to the gateway at each PORT with `nc`, for at most 2 seconds, and prints, a line +/// each, `NAME 0` once it opened, or `NAME 1` once it failed. +const REACH: &str = "gateway=$1; shift; for target in \"$@\"; do \ + nc -z -w 2 \"$gateway\" \"${target#*:}\" /dev/null 2>&1; \ + echo \"${target%%:*} $?\"; done"; /// The placeholder of the template of the scenarios of GPT disks: a disk of two layers, whose /// partitions start at multiples of 1 MiB. const PLACEHOLDER: Disk = Disk { @@ -365,10 +445,212 @@ impl Disk { } } +/// The network of a scenario's template or clone, which the host program reads from a file that +/// the test writes, in the serde form of a plan's network, as `vm_template` writes it: the guest at +/// an address of its own, with egress denied, and no host-loopback access, unless the network says +/// otherwise. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Network { + /// Everything denied, without a proxy, which attaches no NIC. + Deny, + /// Egress allowed, without host-loopback access, which lets the guest reach the gateway's DNS + /// server. + Egress, + /// Egress denied but for one rule, TCP to the gateway at the port of [`Service::Rule`], with + /// outbound host-loopback access. + AllowRule, + /// Egress allowed, with outbound host-loopback access, which lets the guest reach the gateway's + /// DNS server too. + Outbound, + /// A proxy-only network, whose proxy is [`Service::Proxy`], on host loopback. + Proxy, +} + +impl Network { + /// The networks with a NIC that a template takes, which `vm_template` captures. + const WITH_NIC: [Self; 4] = [Self::Egress, Self::AllowRule, Self::Outbound, Self::Proxy]; + + /// Returns the network's name, which names its files. + fn name(self) -> &'static str { + match self { + Self::Deny => "deny", + Self::Egress => "egress", + Self::AllowRule => "rule", + Self::Outbound => "outbound", + Self::Proxy => "proxy", + } + } + + /// Returns the network's serde form, with the guest at `guest`. + fn form(self, guest: &str) -> Value { + let mut form = json!({ + "guestNetwork": guest, + "egress": "deny", + "allow": {"name": "egress.allow", "rules": []}, + "deny": {"name": "egress.deny", "rules": []}, + "ingress": "deny", + "hostLoopback": "deny", + "hostLoopbackForwards": [], + "proxy": null, + }); + match self { + Self::Deny => {} + Self::Egress => form["egress"] = json!("allow"), + Self::AllowRule => { + let port = HOST_SIDE.port(Service::Rule); + form["allow"]["rules"] = json!([{ + "to": [{"cidr": format!("{GATEWAY}/32"), "except": []}], + "ports": [{"protocol": "tcp", "port": port, "endPort": null}], + }]); + form["hostLoopback"] = json!("outbound"); + } + Self::Outbound => { + form["egress"] = json!("allow"); + form["hostLoopback"] = json!("outbound"); + } + Self::Proxy => { + let port = HOST_SIDE.port(Service::Proxy); + form["proxy"] = json!({"port": port, "scheme": "http"}); + } + } + form + } + + /// Returns OpenVMM's arguments with which the restore of a clone of a template of the network, + /// with the guest at `guest`, attaches the template's NIC, as NVX lowers the network: all of + /// them but `--net` and the guest's address, which OpenVMM takes from the snapshot, and none + /// for a network that lets nothing through. + fn restored(self, guest: &str) -> Vec { + let network = serde_json::from_value::(self.form(guest)).unwrap(); + let mut arguments = network.openvmm_arguments().unwrap(); + arguments.drain(..arguments.len().min(2)); + arguments + } + + /// Returns the DNS server that the network's clones' records name, with which the template's + /// guest configured its resolver at boot: the gateway's, for a network that lets the guest + /// reach it. + fn dns(self) -> Option { + matches!(self, Self::Egress | Self::Outbound).then(|| GATEWAY.parse().unwrap()) + } + + /// Returns the URL of the network's proxy, as the guest sees it, which the network's clones' + /// records name, if it has one. + fn proxy(self) -> Option { + (self == Self::Proxy) + .then(|| format!("http://{GATEWAY}:{}", HOST_SIDE.port(Service::Proxy))) + } + + /// Returns the services of the host's side that the network lets a clone reach at its + /// gateway: none without host-loopback access, the allow rule's alone, every one with egress + /// and outbound host-loopback access allowed, and the proxy alone for a proxy-only network. + fn reaches(self) -> &'static [Service] { + match self { + Self::Deny | Self::Egress => &[], + Self::AllowRule => &[Service::Rule], + Self::Outbound => &Service::ALL, + Self::Proxy => &[Service::Proxy], + } + } +} + +/// A service of the host's side of the scenarios' networks: a listener on host IPv4 loopback, +/// which a clone reaches at the same port of its gateway where its network lets it. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Service { + /// The proxy of a proxy-only network. No clone sends it a request; a connection that opens + /// shows that the network lets the clone reach it. + Proxy, + /// The service to which the allow rule of a network lets TCP through. + Rule, + /// A service that no network names. + Other, +} + +impl Service { + /// Every service. + const ALL: [Self; 3] = [Self::Proxy, Self::Rule, Self::Other]; + + /// Returns the service's name, which [`REACH`] prints. + fn name(self) -> &'static str { + match self { + Self::Proxy => "proxy", + Self::Rule => "rule", + Self::Other => "other", + } + } +} + +/// The host's side of the scenarios' networks: the listener of each [`Service`], on host IPv4 +/// loopback, at a port that the host chose, which the networks that the tests write name. The +/// listeners hold their ports until the tests end, so that no other socket takes one. +struct HostSide { + /// The listener of [`Service::Proxy`]. + proxy: TcpListener, + /// The listener of [`Service::Rule`]. + rule: TcpListener, + /// The listener of [`Service::Other`]. + other: TcpListener, +} + +impl HostSide { + /// Binds the listener of each service. + fn bind() -> Self { + let bind = || TcpListener::bind((Ipv4Addr::LOCALHOST, 0)).unwrap(); + Self { + proxy: bind(), + rule: bind(), + other: bind(), + } + } + + /// Returns the listener of `service`. + fn listener(&self, service: Service) -> &TcpListener { + match service { + Service::Proxy => &self.proxy, + Service::Rule => &self.rule, + Service::Other => &self.other, + } + } + + /// Returns the port of `service`. + fn port(&self, service: Service) -> u16 { + self.listener(service).local_addr().unwrap().port() + } + + /// Returns whether a connection arrived at the listener of `service` within `wait`, or at once + /// for no wait, which it accepts and closes. + fn accepted(&self, service: Service, wait: Duration) -> bool { + let listener = self.listener(service); + listener.set_nonblocking(true).unwrap(); + let deadline = Instant::now() + wait; + loop { + match listener.accept() { + Ok(_) => return true, + Err(error) if error.kind() == io::ErrorKind::WouldBlock => {} + Err(error) => panic!("the listener of {service:?} failed: {error}"), + } + if Instant::now() >= deadline { + return false; + } + thread::sleep(Duration::from_millis(10)); + } + } +} + +/// Writes the network `network`, with the guest at `guest`, in a file of its own in `directory`, +/// and returns the file's path. +fn write_network(directory: &Path, network: Network, guest: &str) -> PathBuf { + let address = guest.replace(['.', '/'], "-"); + let path = directory.join(format!("network-{}-{address}.json", network.name())); + fs::write(&path, network.form(guest).to_string()).unwrap(); + path +} + /// The template of a scenario: the generation that a template store of its own captured, in the /// scenario's sandbox, of the platform's copy of the fixtures' Ubuntu EROFS image, or of a GPT /// [`Disk`] of its length, with [`TEMPLATE_MEMORY`] MiB of RAM, of a capacity of -/// [`TEMPLATE_CAPACITY`] MiB. +/// [`TEMPLATE_CAPACITY`] MiB, and a NIC exactly when its [`Network`] lets something through. struct Template { /// The scenario's sandbox, whose store is the template store, until the template drops. sandbox: Option, @@ -389,19 +671,27 @@ impl Template { /// after the 32 hexadecimal digits of the launch, must fit the path of a Unix socket, so the /// scenarios' names are short. fn create(name: &str) -> Self { - Self::capture(name, None) + Self::capture(name, None, None) } /// Creates the sandbox of the scenario `name`, stages the platform's copy of the image, and /// captures the template of the GPT disk `placeholder`, of the image's length, which the /// platform stages beside it, as [`create`](Self::create) does. fn of_disk(name: &str, placeholder: &Disk) -> Self { - Self::capture(name, Some(placeholder)) + Self::capture(name, Some(placeholder), None) } /// Creates the sandbox of the scenario `name`, stages the platform's copy of the image, and - /// captures the template of the GPT disk `placeholder`, if any, and of the image otherwise. - fn capture(name: &str, placeholder: Option<&Disk>) -> Self { + /// captures the template of the image with the network `network`, with the guest at + /// [`GUEST_NETWORK`], as [`create`](Self::create) does. + fn in_network(name: &str, network: Network) -> Self { + Self::capture(name, None, Some(network)) + } + + /// Creates the sandbox of the scenario `name`, stages the platform's copy of the image, and + /// captures the template of the GPT disk `placeholder`, if any, and of the image otherwise, + /// with the network `network`, if any, with the guest at [`GUEST_NETWORK`]. + fn capture(name: &str, placeholder: Option<&Disk>, network: Option) -> Self { let mut sandbox = Sandbox::new(name); let fixtures = Fixtures::find(); let image = stage_platform(&sandbox.root.join("platform"), &fixtures); @@ -414,7 +704,8 @@ impl Template { } }; let (memory, capacity) = (TEMPLATE_MEMORY.to_string(), TEMPLATE_CAPACITY.to_string()); - let options = [ + let network = network.map(|network| write_network(&sandbox.root, network, GUEST_NETWORK)); + let mut options = vec![ OsStr::new("--distro"), &distro, OsStr::new("--distro-identity"), @@ -424,6 +715,9 @@ impl Template { OsStr::new("--memory-capacity"), OsStr::new(&capacity), ]; + if let Some(network) = &network { + options.extend([OsStr::new("--network"), network.as_os_str()]); + } let created = sandbox.create(&options, 0); assert_eq!(created["created"], "captured", "{created:?}"); assert_eq!(created["generation"], GENERATION.to_string(), "{created:?}"); @@ -498,6 +792,13 @@ impl Template { path } + /// Returns the options of a start whose clone has the network `network`, with the guest at + /// `guest`, from a file that they name, which the template's directory holds. + fn network_options(&self, network: Network, guest: &str) -> Vec { + let path = write_network(self.root(), network, guest); + vec!["--network".to_owned(), path.display().to_string()] + } + /// Stages the template's image in the store of `sandbox`, which it creates, for a clone in /// RAM. fn stage(&self, sandbox: &mut Sandbox) { @@ -741,6 +1042,29 @@ impl Cloned { assert!(Lease::of(&store).unwrap().is_none()); } + /// Checks that NVX's plan refused the start's clone before any VMM started, as one that the + /// template cannot serve, with a diagnostic that says `problem`: a failure of the request, by + /// the evidence of invalid settings, which quarantines nothing, and that the start released the + /// lease that the store granted. + fn assert_unserved(&self, problem: &str) { + let started = &self.started; + assert!(started.contains_key("lease"), "{started:?}"); + assert_eq!( + failure(started), + [ + "request", + "invalid-settings", + "plan", + "planned", + "none", + "no-vm" + ], + "{started:?}" + ); + assert_eq!(started["quarantined"], "no", "{started:?}"); + self.assert_refused(problem); + } + /// Checks that the start started the clone's VM, which ended before the clone was ready, with /// `status`, the guest's status of its activation's failure, and that the start printed the /// failure's record, of the request, by `evidence`, at the activation, once the VM exited, @@ -831,6 +1155,34 @@ impl Cloned { .collect() } + /// Checks that the clone reaches, at its gateway, the services of the host's side `reached` + /// alone: a TCP connection that an execution opens to each of them, with [`REACH`], arrives at + /// its listener, while one to each other service fails, and none arrives there. + fn assert_reaches(&mut self, reached: &[Service]) { + let host = &*HOST_SIDE; + // Nothing else connects to the listeners, but a connection that a failed check left. + for service in Service::ALL { + while host.accepted(service, Duration::ZERO) {} + } + let targets = + Service::ALL.map(|service| format!("{}:{}", service.name(), host.port(service))); + let found = self.script(&format!("set -- {GATEWAY} {}; {REACH}", targets.join(" "))); + let expected = Service::ALL.map(|service| { + let status = u8::from(!reached.contains(&service)); + format!("{} {status}", service.name()) + }); + assert_eq!(found, expected, "{reached:?}"); + for service in Service::ALL { + let reach = reached.contains(&service); + let wait = if reach { ARRIVAL } else { NEGATIVE_OBSERVATION }; + assert_eq!( + host.accepted(service, wait), + reach, + "{service:?} of {reached:?}" + ); + } + } + /// Returns the configuration of the clone's activation record, which NVX keeps in the clone's /// sandbox, in its canonical encoding, while the clone holds its lease. fn configuration(&self) -> Configuration { @@ -848,12 +1200,7 @@ impl Cloned { fn assert_vmm_mount(&self, export: Option<(&Export, &str)>) { #[cfg(target_os = "linux")] { - let pid = &self.started["pid"]; - let command_line = fs::read(format!("/proc/{pid}/cmdline")).unwrap(); - let arguments = command_line - .split(|byte| *byte == 0) - .map(|argument| String::from_utf8_lossy(argument).into_owned()) - .collect::>(); + let arguments = self.vmm_arguments(); let mounts = arguments .windows(2) .filter(|pair| pair[0] == "--mount") @@ -871,6 +1218,47 @@ impl Cloned { #[cfg(not(target_os = "linux"))] let _ = export; } + + /// Checks the arguments with which NVX started the clone's VMM, on Linux, as + /// [`assert_vmm_mount`](Self::assert_vmm_mount) does: `policy`, the arguments of the policy of + /// the template's NIC, in order, as the template's key holds them, and no other argument of a + /// network, so no `--net`, since OpenVMM takes the NIC and the guest's address from the + /// snapshot, nor any argument of a network for a template without a NIC. + fn assert_vmm_network(&self, policy: &[String]) { + #[cfg(target_os = "linux")] + { + let arguments = self.vmm_arguments(); + let of_network = |argument: &&String| { + argument.starts_with("--net") || argument.as_str() == "--host-loopback" + }; + assert_eq!( + arguments.iter().filter(of_network).count(), + policy.iter().filter(of_network).count(), + "{policy:?} in {arguments:?}" + ); + assert!( + policy.is_empty() + || arguments + .windows(policy.len()) + .any(|window| window == policy), + "{policy:?} in {arguments:?}" + ); + } + #[cfg(not(target_os = "linux"))] + let _ = policy; + } + + /// Returns the arguments with which NVX started the clone's VMM, which the test, as root, + /// reads on Linux. + #[cfg(target_os = "linux")] + fn vmm_arguments(&self) -> Vec { + let pid = &self.started["pid"]; + let command_line = fs::read(format!("/proc/{pid}/cmdline")).unwrap(); + command_line + .split(|byte| *byte == 0) + .map(|argument| String::from_utf8_lossy(argument).into_owned()) + .collect() + } } /// What an execution of [`VIEW`] found in a clone's root. @@ -1358,6 +1746,7 @@ fn refuses_early(template: &Template, early: Message) { first_partition_bound: None, machine_id: MachineIdMode::Image, sharing: HostFsSharing::default(), + network: None, }; let plan = request.plan().unwrap(); let staged = Staged::read(&sandbox.store).unwrap().unwrap(); @@ -2845,3 +3234,330 @@ fn a_clone_whose_mapping_fails_ends_before_its_sandbox_starts() { ); assert_payload(&template, false); } + +/// Returns the facts that the [`MAP_RESOLVER`] probe found of a root's `/etc/resolv.conf`: the +/// mounts below the root, and the options of the topmost mount at the file, what it shows, and +/// whether a write of it is allowed. +fn resolver_facts(facts: &Printed) -> [&str; 4] { + [ + "mounts", + "resolver.options", + "resolver.kind", + "resolver.write", + ] + .map(|key| facts[&format!("map.{key}")].as_str()) +} + +/// Starts a clone in RAM of `template` in a new sandbox of the scenario `name`, with the start's +/// `options`, checks that the start exits with `status`, and returns the clone. +fn start_with(template: &Template, name: &str, options: &[String], status: i32) -> Cloned { + let options = options.iter().map(String::as_str).collect::>(); + let start = StartOf { + options: &options, + ..StartOf::default() + }; + template.start(name, start, status) +} + +#[test] +#[ignore = "boots VMs; see the module documentation for what they need"] +fn a_template_without_a_nic_serves_clones_without_a_network() { + let template = Template::create("cl-nonic"); + // A clone without a network, and one of a network that lets nothing through, which attaches + // no NIC either, as the template's capture attached none: the template serves both. + let deny = template.network_options(Network::Deny, GUEST_NETWORK); + let mut clones = [("cl-none", Vec::new()), ("cl-deny", deny)].map(|(name, options)| { + let cloned = start_with(&template, name, &options, 0); + cloned.assert_started(); + cloned + }); + + // Neither has a network: no network in its record, and on Linux, no argument of a network of + // its VMM; no network device, and the image's own `/etc/resolv.conf`, an empty file, which no + // bind holds, and which root may write. + for cloned in &mut clones { + assert_eq!(cloned.configuration().network, None); + cloned.assert_vmm_network(&[]); + assert_eq!( + cloned.script(NETWORK_VIEW), + ["devices 0", "resolver 644 regular empty file"] + ); + let facts = cloned.probe(&[MAP_RESOLVER]); + assert_eq!( + resolver_facts(&facts), + ["", "none", "file 0", "allowed"], + "{facts:?}" + ); + } + for cloned in &mut clones { + cloned.stop(); + } + + // A clone of a network with a NIC finds no template there: NVX's plan refuses each before any + // VMM starts. + for network in Network::WITH_NIC { + let options = template.network_options(network, GUEST_NETWORK); + let refused = start_with(&template, "cl-r", &options, CLONE_FAILED); + refused.assert_unserved( + "the adapter's plan of a clone attaches a network, but the template's generation 1 \ + has no NIC", + ); + } + assert!(template.leases().is_empty()); + assert_payload(&template, false); +} + +#[test] +#[ignore = "boots VMs; see the module documentation for what they need"] +fn a_template_serves_the_clones_of_its_own_network_policy_alone() { + let other = "the network of the adapter's plan of a clone is not the one that the template's \ + generation 1 restores its NIC with"; + let address = format!( + "the adapter's plan of a clone gives its guest the network {OTHER_GUEST_NETWORK}, but the \ + template's generation 1 restores its NIC on {GUEST_NETWORK}, from its snapshot" + ); + let none = "the template's generation 1 has a NIC, whose network every clone of it restores, \ + but the adapter's plan of the clone has none"; + let mut policies = Vec::new(); + for network in Network::WITH_NIC { + let template = Template::in_network(&format!("cl-p-{}", network.name()), network); + + // The template serves a clone of its own network: its NIC, which the clone's restore + // attached under the template's policy, unchanged, and a record that names the policy, + // the DNS server with which the template's guest configured its resolver at boot, where + // the policy lets the guest reach the gateway's, and the proxy, if any, and that + // publishes no listener. The NIC lets through what the policy allows alone: the clone + // reaches, at its gateway, the services of the host's side that the policy lets it reach, + // and no other. + let own = template.network_options(network, GUEST_NETWORK); + let mut cloned = start_with(&template, "cl-own", &own, 0); + cloned.assert_started(); + let recorded = cloned + .configuration() + .network + .expect("the record names the network"); + assert_eq!( + (&recorded.dns, &recorded.proxy, recorded.publication), + (&network.dns(), &network.proxy(), Publication::Unpublished), + "{network:?}" + ); + policies.push((network, recorded.policy)); + cloned.assert_vmm_network(&network.restored(GUEST_NETWORK)); + assert_eq!(cloned.script(NETWORK_VIEW)[0], "devices 1", "{network:?}"); + cloned.assert_reaches(network.reaches()); + cloned.stop(); + + // A clone of any other network finds no template there: of each other network with a + // NIC, of the template's policy at another address of the guest, of a network that lets + // nothing through, which attaches no NIC, and without a network. NVX's plan refuses each + // before any VMM starts, and names both addresses where the guest's address alone + // differs. + let mut cases = Network::WITH_NIC + .into_iter() + .filter(|requested| *requested != network) + .map(|requested| (Some((requested, GUEST_NETWORK)), other)) + .collect::>(); + cases.extend([ + (Some((network, OTHER_GUEST_NETWORK)), address.as_str()), + (Some((Network::Deny, GUEST_NETWORK)), none), + (None, none), + ]); + for (requested, problem) in cases { + let options = requested.map_or_else(Vec::new, |(requested, guest)| { + template.network_options(requested, guest) + }); + let refused = start_with(&template, "cl-r", &options, CLONE_FAILED); + refused.assert_unserved(problem); + } + assert!(template.leases().is_empty()); + assert_payload(&template, false); + } + // Each template's key holds a policy of its own, which its clones' records name. + for (index, (network, policy)) in policies.iter().enumerate() { + for (other, other_policy) in &policies[index + 1..] { + assert_ne!(policy, other_policy, "{network:?} and {other:?}"); + } + } +} + +#[test] +#[ignore = "boots VMs; see the module documentation for what they need"] +fn a_clone_binds_the_resolver_of_its_policy_s_dns_server_read_only() { + let template = Template::in_network("cl-dns", Network::Egress); + let own = template.network_options(Network::Egress, GUEST_NETWORK); + let mut generated = own.clone(); + generated.extend(["--machine-id".to_owned(), "generated".to_owned()]); + // Two clones at once: one with a generated machine ID, and one with the image's own. + let mut clones = [ + ("cl-gen", generated, "/etc/machine-id,/etc/resolv.conf"), + ("cl-img", own.clone(), "/etc/resolv.conf"), + ] + .map(|(name, options, mounts)| { + let cloned = start_with(&template, name, &options, 0); + cloned.assert_started(); + (cloned, mounts) + }); + let resolver = format!("nameserver {GATEWAY}"); + for (cloned, mounts) in &mut clones { + // The record names the gateway's DNS server, with which the template's guest configured + // its resolver at boot. + let recorded = cloned + .configuration() + .network + .expect("the record names the network"); + assert_eq!(recorded.dns, Network::Egress.dns()); + + // The guest wrote a resolver file that names it, of mode 0444, which a read-only bind, + // without set-user-ID programs or devices, holds at the root's `/etc/resolv.conf`, below + // the root, after the bind of a generated machine ID: a write there, even as root, finds + // its file system read-only, and the overlay's upper holds nothing there. + let facts = cloned.probe(&[MAP_RESOLVER]); + let fact = |key: &str| facts[&format!("map.{key}")].as_str(); + assert_eq!(fact("mounts"), *mounts, "{facts:?}"); + let options = mount_options(fact("resolver.options")); + assert!( + options.is_superset(&BTreeSet::from(["ro", "nosuid", "nodev"])), + "{facts:?}" + ); + let size = format!("file {}", resolver.len() + 1); + let found = ["kind", "read", "write", "upper"].map(|key| fact(&format!("resolver.{key}"))); + assert_eq!( + found, + [size.as_str(), resolver.as_str(), "refused", "absent"], + "{facts:?}" + ); + assert_eq!( + cloned.script(NETWORK_VIEW), + ["devices 1", "resolver 444 regular file"] + ); + + // The guest reaches that server through the template's NIC: a TCP connection to its DNS + // port opens, which the gateway's DNS proxy accepts itself, whatever the host's resolver + // and its upstream servers do. + assert_eq!( + cloned.script(DNS_REACH), + [format!("server {GATEWAY}"), "dns 0".to_owned()] + ); + } + for (cloned, _) in &mut clones { + cloned.stop(); + } + + // A clone of a disk whose top layer holds a regular file `etc`, below which nothing can be + // bound at `/etc/resolv.conf`, ends before it is ready, with the status of its network + // settings, which attributes the failure to the request's invalid settings. It keeps the + // image's own machine ID, which needs no bind. + let disk = template.disk("etc.gpt", &ETC_FILE); + let own = own.iter().map(String::as_str).collect::>(); + let start = StartOf { + image: Some(Image::Gpt(&ETC_FILE, &disk)), + options: &own, + ..StartOf::default() + }; + let ended = template.start("cl-etc", start, CLONE_FAILED); + ended.assert_unactivated(&template, "invalid-settings", status::ACTIVATION_NETWORK); + assert_payload(&template, false); +} + +#[test] +#[ignore = "boots VMs; see the module documentation for what they need"] +fn a_clone_s_executions_find_the_proxy_of_its_policy() { + let template = Template::in_network("cl-proxy", Network::Proxy); + let own = template.network_options(Network::Proxy, GUEST_NETWORK); + let mut cloned = start_with(&template, "cl-p", &own, 0); + cloned.assert_started(); + let url = Network::Proxy.proxy().expect("the network has a proxy"); + + // The record names the proxy's URL, as the guest sees it, and no DNS server, since the policy + // lets the guest reach nothing but the proxy. + let recorded = cloned + .configuration() + .network + .expect("the record names the network"); + assert_eq!( + (recorded.dns, recorded.proxy.as_deref()), + (None, Some(url.as_str())) + ); + + // An execution finds that URL in each of the proxy's variables, after its own entries, as + // the host gives it from the clone's record, as it gives a launch's executions; one that names + // its own proxy's settings keeps exactly its own environment. + let proxies = PROXY_VARIABLES + .map(|variable| format!("{variable}={url}\\n")) + .concat(); + for (entry, expected) in [ + ("FIRST=1", format!("FIRST=1\\n{proxies}")), + (OWN_PROXY, format!("{OWN_PROXY}\\n")), + ] { + let ran = cloned.exec(&["--identity", "0:0", "--env", entry, "--", "/usr/bin/env"]); + let facts = + ["launch", "status", "stdout", "stderr"].map(|key| &ran[&format!("exec.1.{key}")]); + assert_eq!( + facts, + ["started", "exit 0", expected.as_str(), ""], + "{ran:?}" + ); + } + + // Without a DNS server, the guest binds no resolver: the clone, which has the template's NIC, + // keeps the image's own `/etc/resolv.conf`. + assert_eq!( + cloned.script(NETWORK_VIEW), + ["devices 1", "resolver 644 regular empty file"] + ); + let facts = cloned.probe(&[MAP_RESOLVER]); + assert_eq!( + resolver_facts(&facts), + ["", "none", "file 0", "allowed"], + "{facts:?}" + ); + cloned.stop(); + assert!(template.leases().is_empty()); + assert_payload(&template, false); +} + +#[test] +#[ignore = "boots VMs; see the module documentation for what they need"] +fn a_clone_of_a_template_with_a_nic_maps_its_export_beside_its_resolver() { + let template = Template::in_network("cl-netexp", Network::Egress); + let export = Export::write(&template, "data", &[("marker", "data")], &[]); + let mut options = export.options(&[(".", "/srv/data")], &[]); + options.extend(template.network_options(Network::Egress, GUEST_NETWORK)); + options.extend(["--machine-id".to_owned(), "generated".to_owned()]); + let mut cloned = start_with(&template, "cl-ne", &options, 0); + cloned.assert_mapped(1); + + // The record names the export, with its one mapping, and the network's DNS server. On Linux, + // the restore bound the export's directory to the template's dormant filesystem slot, and + // attached the template's NIC under its policy. + let configuration = cloned.configuration(); + let recorded = configuration.export.map(|export| export.kind); + assert_eq!( + (recorded, configuration.mappings), + (Some(ExportKind::Directory), 1) + ); + let dns = configuration.network.and_then(|network| network.dns); + assert_eq!(dns, Network::Egress.dns()); + cloned.assert_vmm_mount(Some((&export, "rw"))); + cloned.assert_vmm_network(&Network::Egress.restored(GUEST_NETWORK)); + + // Below the root, the binds of the generated machine ID and of the resolver, which the + // activation made, then the export's mapping, which came once the clone was ready. + let probe = format!("{MAP_DATA} resolver=etc/resolv.conf"); + let facts = cloned.probe(&[&probe]); + let fact = |key: &str| facts[&format!("map.{key}")].as_str(); + assert_eq!( + fact("mounts"), + "/etc/machine-id,/etc/resolv.conf,/srv/data", + "{facts:?}" + ); + assert_eq!(fact("resolver.read"), format!("nameserver {GATEWAY}")); + let data = ["kind", "entries", "write"].map(|key| fact(&format!("data.{key}"))); + assert_eq!(data, ["directory", "marker", "allowed"], "{facts:?}"); + assert_eq!(fact("marker.read"), "data", "{facts:?}"); + cloned.stop(); + let written = [("marker", "data"), ("written", "runtime-adapter")]; + assert_eq!(export.tree(), tree_of(&[], &written)); + assert!(template.leases().is_empty()); + assert_payload(&template, false); +}