Skip to content

guest: mount the runtime's file systems in a layered root - #1276

Merged
Pedro Henrique Penna (ppenna) merged 1 commit into
feature/nvx-refactorfrom
esaurez/slim-2.4.1-sl7.1a-20261103
Nov 6, 2026
Merged

Pedro Henrique Penna (ppenna) merged 1 commit into
feature/nvx-refactorfrom
esaurez/slim-2.4.1-sl7.1a-20261103

Conversation

@esaurez

@esaurez Enrique Saurez (esaurez) commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Part of #1104: the space mounts its root's runtime file systems. Builds on the merged #1262.

What changes

Root::mount_runtime(time_status), which is crate-private, and RuntimeMounts, in the hidden guest::root, give an init the one-time runtime setup that it makes before it switches into its root:

  • It first makes every mount of the root's tree nosuid and nodev. It then mounts, in order, procfs at /proc, sysfs read-only at /sys, a tmpfs at /dev with an execution's device nodes and links, devpts at /dev/pts, a tmpfs at /dev/shm, and a tmpfs at /run, each with the options with which an execution's entry mounts it; /run, which an entry does not mount, is nosuid and nodev, with mode 0755.
  • With a time-status directory, it binds that directory read-only, nosuid and nodev at /run/nvx/time, as Entry::bind_runtime does. Without one, it binds nothing there.
  • It opens each mount point beneath the root with openat2, through no symbolic link or magic link and without crossing a mount, and creates a missing one with mode 0755, less what the umask withholds. A mount point where something is mounted already is refused as Error::Occupied. So is a call while the root holds a runtime mount, before it opens or restricts anything, since restricting the tree again would make an earlier call's /dev and /dev/pts nodev: a second call changes nothing, and neither does a call after one whose undo left a mount for the teardown.
  • Runtime setup also refuses an existing live share, aggregate child, or mapping before changing anything: mounting /run over an existing /run/app would hide it from the caller and the teardown. Runtime setup comes first. The persistent mapper recognizes the runtime-owned /run tmpfs, so later shares and mappings beneath it can create their targets there and are unmounted before the tmpfs.
  • The root records the mounts with its shares, so its teardown unmounts them after its mappings, with its shares, the later first, and before the overlay. If a mount fails, the call unmounts the mounts that it made, the later first; one that fails to unmount stays for the teardown.
  • Every newly attached runtime filesystem is checked at its named target before its path is recorded. If a target moves between lookup and attachment, the root detaches the actual mount through its descriptor rather than unmounting the old path. A failed detach, including after a time-status bind's ownership lookup fails, retains the descriptor and the runtime mount's identity. Rollback retries the detach before undoing its parent mounts; a surviving mount blocks repeated setup without further kernel calls and remains owned for teardown. A failed teardown reports the actual detach error and the correct runtime mount.
  • RuntimeMounts names the fixed, ordered runtime mounts, and Mount::Runtime names one in errors.

No code calls mount_runtime yet: nvx-init, which #1115 adds, will. As #1076 asks of crate-private code whose caller comes in a later PR, the method is crate-private, with #[cfg_attr(not(test), expect(dead_code, reason = "nvx-init calls it (#1115)"))], rather than public, even hidden. RuntimeMounts::target, which only the root's own code uses, is crate-private too. RuntimeMounts stays public, since the public Error names a runtime mount through Mount::Runtime. The public docs name the method without a link, so that the documentation of hidden items links to no private item. The expectation's gate names test, so the test layout counts it as a test hook, which its allowlist records for root.rs.

When nvx-init calls mount_runtime, #1115 removes the expectation and the test hook that the allowlist records for it.

The file systems come from guest::sys::entry, which now names each one's type, parameters and attributes once, as a FileSystem constant, for the entry and the root. The root mounts them through the entry's own fsopen, fsconfig and fsmount helpers, and creates the device nodes with the entry's code, then gives them mode 0666, since a root, unlike an entry's child, keeps its caller's umask. The per-execution path is unchanged in behavior: it still opens its targets from AT_FDCWD through the same helpers, with the same flags and in the same order. The root's kernel seam gains the new mount, the tree's restriction and the device nodes, which the fake kernel records.

Size

361 core lines in 7 counted files, measured against 256ebe3d, all under nvx-rs/src/guest/: root.rs, sys/entry.rs, root/kernel.rs, sys/mod.rs, entry.rs, root/share.rs and mappings/mapper.rs. This remains under the issue's 500-line stop. The seventh file preserves the existing mapper attach error and its surviving descriptor without changing the public bind API or mappings.rs. The allowlist's one new line, in scripts/test-layout-allowlist.json, is in a kind of file that #1076 does not count; counting it too gives 362 core lines in 8 files.

nvx-rs/public-api/linux.txt gains 12 lines, all hidden: RuntimeMounts and its 7 variants, Mount::Runtime and Error::Restrict, each with its field. The crate-private Root::mount_runtime and RuntimeMounts::target are not in it.

Tests

New tests:

  • guest::root::tests::runtime, 13 tests with the fake kernel: the restriction, then the mounts in order with their options, then the time status's bind, and the teardown's order; no bind without a time status; a failure at each of the 7 mounts, which unmounts the earlier ones; a failed restriction, which mounts nothing, and failed device nodes or devpts mount, which undo the call; a symbolic link at a mount point, and a second call, refused before it reaches the kernel; an undo whose unmount fails, which leaves that mount for the teardown, and a later call, refused the same way. The /run regressions cover refusal after an existing share, child or mapping, later shares and mappings on /run with mapper-first teardown, and a failed /run ownership check or an undo that leaves /run mounted. Two regressions cover an attached time-status bind whose lookup and detach fail: cleanup after its target moves, refusal of repeated setup without kernel calls, and reporting a persistent detach failure during teardown. Two more rename targets during move_mount: every runtime filesystem is verified and detached before registration; failed detaches on /dev, /dev/pts and /run are retained, block repeated setup, and are either retried successfully or reported with the right mount and errno at teardown.
  • guest::root::tests::privileged, 4 ignored tests that need root and Linux 6.8 or later and mount on a tmpfs root in their thread's private mount namespace: the options, modes, device nodes under a umask of 077, links, the read-only time status and the teardown; a call that fails part of the way, and a second call, after which every mount keeps its options and /dev/null is still writable; refusal after an existing mapping, which remains reachable; and mappings beneath an already-mounted runtime /run, which stay reachable and are unmounted before it.

Every existing test is kept. check_test_changes.py reports 4 changes, hence tests-modified: 3 to existing test helpers, and 1 to the test layout's allowlist:

  • guest::root::kernel::tests::Operation gains NewMount, and Call gains NewMount, RestrictTree and CreateDevices, for the seam's new operations.
  • The fake kernel's open_tree creates its tree's memory file through tree_file, which new mounts share; it behaves as before.
  • scripts/test-layout-allowlist.json allows nvx-rs/src/guest/root.rs one test hook, the expectation on mount_runtime.

By name, the kept tests of the changed code are the 64 of guest::root::tests, the 11 of the root's share, block and bootstrap modules, the 31 of guest::entry and guest::sys::entry, whose helpers the root now shares, and the 33 of guest::mappings::mapper, whose test module shares the root's fake kernel. Their bodies are unchanged; none is removed or renamed.

The 139 kept tests
guest::root::tests::
  assembly_mounts_the_image_and_the_scratch_under_the_overlay
  devices_are_found_when_they_appear_and_missing_ones_time_out
  an_assembly_waits_for_its_devices_until_its_deadline_at_the_latest
  a_device_of_another_size_is_refused_before_it_is_flushed
  the_expected_uuid_is_checked_in_the_superblock_before_the_mount
  a_failed_assembly_unmounts_what_it_mounted_and_reports_what_stays
  a_runtime_directory_that_the_overlay_options_reserve_is_refused
  a_runtime_directory_whose_path_is_not_canonical_is_refused
  a_root_mounts_nothing_through_a_symbolic_link
  new_upper_and_work_directories_have_mode_0755_whatever_the_umask
  a_fresh_upper_s_directories_must_be_missing_or_empty
  the_freshness_check_takes_one_entry_of_a_directory_and_opens_none
  a_runtime_directory_that_another_root_holds_is_refused
  a_runtime_directory_where_a_file_system_is_mounted_is_refused
  the_kernel_finds_its_mount_points
  the_kernel_shows_a_mount_s_options
  a_thread_with_private_tables_finds_its_mount_points_and_options
  a_mount_s_options_are_the_last_field_of_its_line_in_the_mount_table
  a_runtime_directory_where_a_directory_is_bound_is_refused
  a_gpt_disk_s_layers_are_mounted_under_the_overlay_top_first
  both_overlay_modes_assemble_on_both_uppers_with_their_own_option_sets
  a_tmpfs_upper_needs_no_scratch_device
  a_refused_option_set_fails_without_a_fallback
  an_overlay_that_the_kernel_mounts_without_its_mode_in_effect_is_refused_and_unmounted
  options_that_the_kernel_does_not_show_have_their_defaults
  effective_options_that_cannot_be_read_fail_the_assembly
  overlay_options_that_a_mount_cannot_pass_are_refused_before_any_mount
  up_to_195_layers_fit_in_the_overlay_s_options_below_run_nvx
  the_journal_policy_is_checked_in_the_scratch_s_superblock_before_any_mount
  a_device_whose_access_mode_is_not_its_role_s_is_refused_before_it_is_flushed
  a_tmpfs_upper_is_unmounted_last_and_every_failure_reported
  a_scratch_s_file_system_is_synced_right_before_its_unmount
  a_scratch_whose_sync_fails_stays_mounted_and_the_failure_is_reported
  a_gpt_disk_that_differs_from_the_expected_identities_is_refused_before_any_mount
  a_gpt_disk_without_a_layer_is_refused_before_any_mount
  a_layer_that_is_not_ext4_or_whose_journal_needs_a_recovery_is_refused_before_any_mount
  a_missing_partition_fails_at_once_before_any_mount
  a_reread_asks_the_kernel_for_the_distro_disk_s_table_once_the_device_appears
  the_kernel_rereads_a_partition_table_that_changed_under_it
  the_first_partition_is_returned_as_opaque_bytes_within_its_bound
  a_teardown_unmounts_the_layers_top_first_and_reports_every_failure
  a_layer_that_a_failed_unmount_left_keeps_the_runtime_directory_occupied
  what_a_share_s_target_lacks_is_created_with_its_mode_whatever_the_umask_or_a_default_acl
  shares_are_mounted_restricted_and_torn_down_first_in_reverse_order
  refused_shares_mount_nothing
  a_root_has_one_aggregate_and_one_that_failed_part_of_the_way_latches_it
  a_child_whose_restriction_fails_is_never_attached
  a_child_that_the_aggregate_lacks_or_holds_as_another_kind_binds_nothing
  a_failed_unmount_is_reported_and_the_later_ones_still_attempted
  a_share_through_a_link_or_onto_another_mount_is_refused_and_latches_the_root
  a_share_or_a_mapping_that_a_rename_moved_and_that_stays_is_the_teardown_s
  mappings_apply_beneath_the_overlay_in_order_and_go_first_at_the_teardown
  a_root_in_run_nvx_mounts_the_host_export_where_its_boot_token_names_it
  the_host_export_is_mounted_out_of_the_root_and_unmounted_after_its_mappings
  a_refused_tag_creates_and_mounts_nothing_and_a_failed_export_latches_the_root
  the_host_export_is_mounted_through_no_symbolic_link
  a_hostfs_directory_that_is_there_already_must_be_private
  a_dropped_root_is_torn_down_once
  bootstrap_moves_every_process_but_kernel_threads_and_applies_the_resources
  bootstrap_mounts_the_hierarchy_unless_the_parent_is_a_cgroup
  bootstrap_names_the_failed_step_and_keeps_the_earlier_changes
  bootstrap_accepts_a_missing_sysctl_only_without_user_namespaces
  bootstrap_fails_while_a_process_keeps_returning_to_the_parent
  bootstrap_succeeds_when_the_last_pass_empties_the_parent
guest::root::share::tests::
  targets_are_canonical_absolute_paths_outside_the_runtime_s_mounts
  tags_and_child_names_are_plain_names
  the_export_s_directory_is_created_private_whatever_the_umask
  a_directory_is_private_to_its_owner_when_its_group_and_others_have_no_permission
  an_export_s_mode_is_the_access_of_its_mount
guest::root::block::tests::
  sizes_are_canonical_decimal_counts
  a_partition_s_node_has_the_name_that_the_kernel_gives_it
  the_superblock_names_an_erofs_uuid_or_none
  the_superblock_tells_whether_an_ext4_journal_exists_and_needs_a_recovery
guest::root::bootstrap::tests::
  kernel_threads_are_known_by_their_flags
  membership_lists_are_decimal_lines
guest::entry::tests::
  the_allowlist_holds_the_thirteen_capabilities
  capability_sets_add_remove_and_list_their_members
  every_capability_outside_the_allowlist_is_refused
  only_user_id_zero_may_hold_capabilities
  published_listeners_refuse_binding_and_raw_sockets
  invalid_roots_ids_groups_and_hostnames_are_refused
  passwd_entries_are_parsed_and_checked
  group_entries_are_found_by_id
  existing_accounts_are_read_below_the_root
  account_databases_are_bounded_regular_files_reached_through_no_link
  an_entry_needs_a_root_directory
  machine_ids_are_version_4_uuids_in_lowercase_hexadecimal
  a_machine_id_is_generated_once_per_file
  a_generated_machine_id_has_mode_0444_whatever_the_umask
  runtime_binds_need_a_mount_root_unless_there_are_none
  runtime_binds_are_made_in_order_and_removed_in_reverse
  a_failed_runtime_bind_removes_the_binds_before_it
  a_failed_runtime_bind_names_the_binds_before_it_that_stay
  a_runtime_bind_that_stays_is_reported
  runtime_sources_are_the_directories_beside_their_files
  only_a_link_at_a_runtime_file_of_etc_is_removed
  device_sets_select_their_nodes
  each_entry_stage_reports_its_own_failure_and_runs_nothing
  a_denied_umask_fails_the_proc_stage_and_runs_nothing
  an_entered_program_leads_a_session_without_a_terminal_or_the_callers_descriptors
  an_entered_program_ignores_and_blocks_no_signal_of_its_caller_s
  an_entry_needs_a_placement_and_neither_a_root_nor_a_check
  privileged_entries_see_their_own_view_and_identity
  privileged_runtime_binds_are_removed_before_a_teardown
guest::sys::entry::tests::
  capability_sets_split_into_two_data_words
  the_kernel_structures_have_their_uapi_sizes
guest::mappings::mapper::tests::
  mappings_are_restricted_copies_attached_in_order
  targets_are_created_with_their_modes_whatever_the_umask
  targets_are_created_with_their_modes_whatever_a_default_acl
  zero_mappings_do_no_work
  links_at_any_component_are_refused
  a_component_that_is_not_a_directory_is_refused
  sources_and_targets_must_be_of_one_kind
  targets_are_created_only_on_the_root_s_own_mounts
  targets_that_would_shadow_a_mapping_or_a_mount_are_refused
  a_mapping_covers_the_root_of_a_mount_that_the_root_owns
  reserved_targets_and_their_ancestors_are_refused
  the_first_failure_latches_the_mapper
  a_failure_at_any_step_leaves_nothing_mounted
  a_mapping_that_a_rename_moved_is_detached_and_refused
  what_a_rename_puts_in_the_place_of_a_created_component_keeps_its_mode
  a_teardown_unmounts_in_reverse_order_and_reports_each_failure
  a_runtime_bind_skips_the_checks_of_a_host_mapping_but_not_the_walk
  runtime_binds_unbind_in_reverse_order_and_report_each_failure
  a_staged_mount_moves_onto_its_target_with_its_restrictions
  a_target_root_is_the_root_of_a_mount_of_a_whole_file_system
  mappings_name_paths_below_their_roots
  an_empty_source_maps_the_source_root_itself_from_beneath_it
  errors_name_what_failed
guest::mappings::mapper::tests::privileged::
  a_target_root_shows_its_whole_file_system
  links_and_magic_links_at_every_component_are_refused
  a_rename_race_never_mounts_outside_the_target
  kinds_nested_targets_and_reserved_targets_are_checked
  an_empty_source_maps_a_copy_of_the_source_root_s_own_mount
  a_mapping_covers_the_root_of_a_mount_only_if_the_root_owns_it
  a_workload_that_is_not_root_enters_what_a_mapper_created_whatever_the_umask_or_a_default_acl
  a_read_only_mapping_is_never_visible_writable
  a_teardown_unmounts_each_mapping_and_reports_a_busy_one
  a_thread_with_a_descriptor_table_of_its_own_tears_its_mappings_down

Validation

Current head e4d4bca7 is one logical commit on dev base 256ebe3d, with tree 9cbdbd90087f449d0b4e58dea28b042c28843d72 and OpenVMM pin 9cec2b89. The rebase had no conflicts. Older-head results are not counted as qualification of this corrected head.

  • Both native Rust action matrices pass at e4d4bca7: feature-set Clippy, default/all/no-default tests, real artifact bundling with NVX_BUNDLE unset, warning-denied documentation, MSRV, native runtime-adapter configurations, OpenVMM vectors/profiles and release CLI builds. Linux also passes both public-API snapshots, the macOS check, guest-binary lint/build/tests and the adapter's guest-only configuration.
  • All 13 runtime-module regressions and all 19 privileged root, mapper, activation and entry cases pass at this head, with no ignored cases in those runs.
  • Alpine and Ubuntu images were assembled natively from this head's freshly built guest binaries; guest-binary source identity is 666ab612429947d84add4c11441ef5c5cf9421e45bb1a72f8dda7a07dcb205b4. The same guest-image bytes and static adapter guest are staged for both backends and checksum-verified.
  • Independent read-only source review found no blocking correctness or scope issues, including in the descriptor correction and its applicability after the base change.
  • Complete native Python/CLI and quality commands pass on both platforms. Windows uses native CPython 3.14.9 with a POSIX shell on PATH: the full unit command reports 1810 tests, 67 skipped, and the previously shell-gated canceled-capture case executes; adversarial reports 84 tests, 11 skipped. Linux's full unit command reports 1810 tests, 30 skipped; adversarial reports all 84 tests with no skips. Both host-resolver runs report 4 tests, and the Linux-only Specula command reports all 25 tests. Every counted command has its runner's own successful summary; failed earlier environment attempts are retained separately.
  • managed-exec-config, sandbox-lifecycle, sandbox-proxy-only, sandbox-ram-upper, private-network-ingress and time-abi-conformance pass on both WHP and MSHV, using their default processor selections. The complete canonical adapter suite passes on each: 156 scenarios across 11 targets, with every runner reporting its expected positive count and no ignored cases. Test executables were compiled and checksum-verified before the guest-only phase; no compilation occurred during VM execution.
  • Runtime inputs are the native, checksum-verified kernel and backend-specific OpenVMM artifacts from release v0.1.0-dev.256ebe3dd9c2, preserving that producer identity separately from the candidate's CLI, guest binaries and images. The kernel SHA-256 is 692ac2a9f351aa5a31dcf1810782d82c1a83a0f1fd0b3edcf4fad9c0d94cfe81; the OpenVMM source pin is 9cec2b89. Provenance validates against this checkout, and consumed bytes and the source head remain unchanged through both complete VM runs.

Complete local qualification and independent source review apply to this exact head. The automatic GitHub Copilot review of the published head is handled separately.

The original WHP CI failure was a listener timeout in vm_layered::an_allow_rule_lets_only_its_destination_through. That run checked out synthetic merge 03e2a8fe, not the source head alone. The individual case and the complete 43-case vm_layered target subsequently passed locally both on source head 6be531ec and on that exact synthetic merge using its CI-produced guest and OpenVMM artifacts. The timeout has only been observed on the CI runner; its underlying cause is unproven, so this PR makes no speculative networking change. The separate advisory NFV run failed before producing findings because of a missing context_input import; no workflow change is included.

Retained RED evidence is explicitly older-head evidence: the second-call tests fail at f99a0c12 with the later tests applied, including a real /dev/null write refused after the repeated restriction. At ddf76e61 with the later tests applied but without the correction, the three fake-kernel and two privileged /run regressions fail. The new moved-bind regression also failed on the unchanged production implementation before the descriptor-retention fix: the mount still existed after teardown.

Both filesystem-rename regressions fail against 423fed09 production code: procfs setup reports success while its moved mount remains after teardown, and /dev loses the descriptor needed to refuse repeated setup and clean up its moved mount. They pass with the attachment verification and typed descriptor retention.

KVM runtime checks remain for CI; no KVM hardware result is claimed here.

@esaurez Enrique Saurez (esaurez) added the tests-modified Changes existing tests, test data, or test wiring label Nov 4, 2026
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

This pull request changes existing tests

It modifies or removes 4 existing test asset(s), listed below. Review each with care: a change to a test can hide a regression that the test caught. See doc/contribute.md#changes-to-existing-tests.

Test code

Change What Before After
modified helper enum Operation in guest::root::kernel::tests nvx-rs/src/guest/root/kernel/tests.rs:28 nvx-rs/src/guest/root/kernel/tests.rs:29
modified helper enum Call in guest::root::kernel::tests nvx-rs/src/guest/root/kernel/tests.rs:68 nvx-rs/src/guest/root/kernel/tests.rs:71
modified helper fn open_tree in guest::root::kernel::tests, impl MappingKernel for FakeKernel`` nvx-rs/src/guest/root/kernel/tests.rs:754 nvx-rs/src/guest/root/kernel/tests.rs:817

Test policy

Change What Before After
loosened allowlist entry nvx-rs/src/guest/root.rs (the seams allow 1 test hooks) scripts/test-layout-allowlist.json

Relocated unchanged: 0; added: 55. Compared the merge base 256ebe3dd9c2 with e4d4bca74ec9.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A repeated mount attempt applies nodev to existing device mounts before returning Error::Occupied, leaving the previously working runtime unable to access device nodes such as /dev/null.

1 open issue
What changed in this PR

Adds one-time runtime filesystem setup to the guest’s layered root, preparing for nvx-init under #1104 while reusing the existing per-execution mount helpers.

Changes:

  • Adds runtime mounts, optional read-only time-status binding, rollback, and teardown tracking.
  • Shares filesystem definitions and device creation helpers between entry and root setup.
  • Adds fake-kernel and privileged tests, documentation, and hidden API snapshot entries.
File Description
scripts/​test-layout-allowlist.json Records the temporary dead-code expectation’s test hook.
nvx-rs/​src/​guest/​sys/​mod.rs Exposes shared runtime filesystem helpers internally.
nvx-rs/​src/​guest/​sys/​entry.rs Extracts filesystem definitions and reusable mount and device helpers.
nvx-rs/​src/​guest/​root/​tests/​runtime.rs Tests mount ordering, failures, rollback, and teardown.
nvx-rs/​src/​guest/​root/​tests/​privileged.rs Checks real mount options, devices, bindings, and cleanup.
nvx-rs/​src/​guest/​root/​tests.rs Registers the new test modules.
nvx-rs/​src/​guest/​root/​share.rs Makes the mount-point opener available to root setup.
nvx-rs/​src/​guest/​root/​kernel/​tests.rs Extends the fake kernel with runtime mount operations.
nvx-rs/​src/​guest/​root/​kernel.rs Adds kernel operations for mounts, restrictions, and devices.
nvx-rs/​src/​guest/​root.rs Implements runtime setup, rollback, tracking, and errors.
nvx-rs/​src/​guest/​entry.rs Shares the time-status target and binding helper internally.
nvx-rs/​README.md Documents runtime setup and privileged test commands.
nvx-rs/​public-api/​linux.txt Records the new hidden runtime mount and error types.

Review effort: Balanced

Comment thread nvx-rs/src/guest/root.rs Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Mounting the /run tmpfs hides supported shares such as /run/app and breaks teardown, while mounting it earlier still causes mapper ownership errors; coordinated mount handling and regression coverage are needed.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread nvx-rs/src/guest/root.rs Resolved
@esaurez
Enrique Saurez (esaurez) force-pushed the esaurez/slim-2.4.1-sl7.0-20261103 branch from 83da90b to 6c6b40f Compare November 4, 2026 18:30
Base automatically changed from esaurez/slim-2.4.1-sl7.0-20261103 to dev November 4, 2026 19:00
Copilot AI balanced review requested due to automatic review settings November 5, 2026 18:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues block approval of the runtime filesystem setup changes.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@esaurez
Enrique Saurez (esaurez) force-pushed the esaurez/slim-2.4.1-sl7.1a-20261103 branch from 1fe929c to 6be531e Compare November 5, 2026 18:59
@esaurez
Enrique Saurez (esaurez) marked this pull request as ready for review November 5, 2026 19:38
Copilot AI balanced review requested due to automatic review settings November 5, 2026 19:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A time-status bind can remain untracked after post-attach lookup and detach failures, escaping rollback and teardown and potentially keeping /run and the overlay busy.

1 open issue

Review effort: Balanced

Comment thread nvx-rs/src/guest/root.rs Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A critical rename race between target lookup and mount attachment can mount filesystems at unintended paths and leave them mounted after rollback and teardown.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread nvx-rs/src/guest/root.rs Resolved
Part of #1104.

Add the root's one-time runtime filesystem setup using the existing entry
mount primitives. Restrict the root tree before mounting proc, read-only
sysfs, devices, devpts, shared memory and run, optionally bind the time
status read-only, and unwind a partial setup.

Require runtime setup before live shares or mappings so that the run tmpfs
cannot hide them. Register that tmpfs with the persistent mapper so later
targets beneath it can be created and removed before the runtime mounts.

Keep the entry point crate-private until init calls it, preserve existing
per-execution behavior, and cover mount ordering, refusal and rollback with
fake-kernel and privileged tests.

Verify every runtime attachment before recording its path. Retain the mount
descriptor when its post-attach check or time-status lookup and detach
fail, so rollback and teardown can retry cleanup after a rename without
losing ownership of the mount.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 1930f155-69ef-41b6-9495-323b84ac76f7
@esaurez
Enrique Saurez (esaurez) force-pushed the esaurez/slim-2.4.1-sl7.1a-20261103 branch from 423fed0 to e4d4bca Compare November 5, 2026 23:28
Copilot AI balanced review requested due to automatic review settings November 5, 2026 23:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are recorded for the runtime filesystem setup change.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@esaurez
Enrique Saurez (esaurez) changed the base branch from dev to feature/nvx-refactor November 6, 2026 00:34
@ppenna
Pedro Henrique Penna (ppenna) merged commit d8f1e45 into feature/nvx-refactor Nov 6, 2026
119 of 121 checks passed
@ppenna
Pedro Henrique Penna (ppenna) deleted the esaurez/slim-2.4.1-sl7.1a-20261103 branch November 6, 2026 05:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat-nvx-refactor tests-modified Changes existing tests, test data, or test wiring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants