pub fn from_legacy_backend_json(json: &str) -> Result<Config, Error>Expand description
Parses JSON written by to_legacy_backend_json, or any JSON in the form
a serialized Config had before Config::backend existed, and recovers
Config::backend from the fifteen legacy backend keys.
The keys are read exactly as they were read while each was a Config
field: a key that is absent takes the default that field had, and a key of
the wrong type fails the parse. Each key then supplies every capability that
replaced a read of it, so a decoded configuration behaves as the same JSON
did before:
discover_live_file_metadatasupplies the three descriptor and loopback facts that were each a read of it;backend_is_kvmsupplies the two behaviours it selected that remain capabilities,provides_process_signal_controlandemulates_child_waits(the other three are now answered by the backend itself: refusing a non-leader exec is a typed refusal it reports per exec, thegettimeofdayrepair runs on every backend through itstime(2)probe andGuest::storable_memory_ranges, and the user address limit is each guest’s ownGuest::user_address_limitreport);- every other key supplies the one capability of the same meaning.
backend_supports_madvise supplies no capability any more: it said the
tool could forward every madvise advice to the backend, which every backend
now accepts, refusing an advice it does not implement itself. Since
supports_madv_dontneed was deleted, MADV_DONTNEED had been forwarded
whatever this key said.
This inverts to_legacy_backend_json for every capability value the keys
can express, which includes every backend’s own constant except for
capabilities added after the legacy form froze: those never enter it, as
record_host_inputs does not, and read back as their default. There are
thirteen. process_exits_complete_asynchronously and
virtualizes_guest_sigalrm are true only for in-guest LiteInst, which
never travels through this DBT-only form.
supports_blocked_wait_signal_interruption,
delivers_preemption_timer_events and
runs_guest_code_between_injections read back as false, the value DBT
has and the value their earlier Config fields read back as; so do
reports_sigreturns and the four capabilities split out of
supports_blocked_wait_signal_interruption (kernel_signal_state_is_guests,
kernel_signal_targets_are_predictable,
host_task_reads_reach_guest_threads, host_timed_signals_are_physical),
false for DBT too. provides_guest_backtraces reads back as true, the
ptrace value it takes from the starting constant and DBT’s value; the
two backends that report false (in-guest LiteInst and KVM) travel
through this form only inside the versioned envelope.
places_orphans reads back as false and publishable_parent_death_signals
as the empty set, DBT’s values; KVM, the one backend that reports
otherwise, travels through this form only inside the versioned envelope
too.
cpuid_virtualized_by_backend supplies no capability either: it said the
backend installed a CPUID policy of its own, which no backend does any
more (KVM stopped with Reverie 0f4d8852). It is still written, as false,
so the legacy form keeps its bytes, and an input that
says true fails the parse rather than being read as a policy no backend
has.
backend_defers_vfork_child_registration supplies no capability either: it
said the backend registered a vfork child only after the parent’s call
returned, which Reverie’s backend contract now allows of every backend. It
is written as false, its value on DBT, so the legacy form keeps its bytes.
The reader still takes it as one of the fifteen keys, so it keeps its
position in the array form, must be a boolean and may appear once, and
ignores its value (KVM wrote true).
backend_supports_madvise is written as true, its value on DBT, so the
legacy form keeps its bytes. The reader still takes it as one of the fifteen
keys, so it keeps its position in the array form, must be a boolean and may
appear once, and ignores its value (KVM wrote false).
syscall_clobbers_virtualized_by_backend supplies no capability either: it
said the backend left the registers a syscall instruction clobbers as a
native return would, which Reverie’s backend contract now requires of every
backend (with the exceptions that contract names). It is written as false,
its value on DBT, so the legacy form keeps its bytes. The reader still takes it as one of the fifteen keys, so
it keeps its position in the array form, must be a boolean and may appear
once, and ignores its value (SaBRe and KVM wrote true).
backend_virtualizes_capability_prctls supplies no capability either: it
said the backend answered the capability-set prctls itself, and every
backend now passes them to the kernel. It is written as false, so the
legacy form keeps its bytes, and true fails the parse.
kvm_shared_dequeue_timers supplies no capability. It was read into a
Config field that chose the controlled signal path, and that choice is
now made from the capabilities, Config::sequentialize_threads and the
control the backend offers. It is read as it was, a boolean that is false
when absent, and the parse then fails unless it equals backend_is_kvm && sequentialize_threads, the value the production launcher always wrote. An
accepted input whose capabilities are those of the backend that runs it
selects the path it selected before. An input that would select another,
such as true without backend_is_kvm, or absent beside backend_is_kvm
and sequentialized threads, fails the parse rather than being silently
reinterpreted. (backend_is_kvm given to a backend that offers no control,
such as DBT, already misdescribed that backend and stays outside this
guarantee; the production launcher never writes it.) A failed parse is
handled like any malformed value: the DBT standalone JSON reader falls
back to its strict default configuration and emits its
could not parse HERMIT_DBT_DETCONFIG warning.
Everything else is read as the legacy form was read, by Config’s own
derived deserializer with the legacy keys taken out before it sees them:
- In an object, a key the legacy form did not name is ignored, whatever its
value.
backendis such a key, so it is ignored rather than read as the field it is now; no production writer emits it. A key the legacy form named fails the parse when it appears twice or holds the wrong type. - A JSON array lists the fields by position, as serde reads any derived
struct. The positions are those of the legacy form, which are the key
order of
to_legacy_backend_json: the fifteen legacy keys stand whereConfig::backendstands. Too many elements fail the parse; too few leave the fields after them missing, each taking its default or failing the parse as the derived deserializer decides for that field.