Repository navigation
fix: 0.7.3 backports - #3019
fix: 0.7.3 backports#3019
Conversation
…#2714) T99. The hostname proxy reads the target box's runtime-published ports (an allowed expose, a published listener) from its live relay gate when the name resolves, so its verdict admits exactly the ports a direct connection reaches. Admitted requests log their route source at info, and refusals record route_source=none. Backport of #2714, folded from #2724. Adapted to the line: - BoxGate, BoxPolicy and boxes::DynamicIngress become SessionGate, sessions::SessionPolicy and sessions::DynamicIngress. - crate::traced::spawn becomes tokio::spawn in the new tests. - The line's spawn_backend_on takes a full address, so proxy_forwards_runtime_published_port picks its port with a probe listener. - The parity proptest checks the gate that carries the runtime publishes and asks admits_tcp, since admits_direct_tcp covers only the declared ports here. Also keeps proxy_refuses_a_withdrawn_port_like_direct (NET-069, from #2732): it publishes and withdraws through the gate only, because the line's listen watcher has no record_dynamic_hold. (cherry picked from commit 7097b96)
…2718) T109. A port outside the box's --dynamic-range is refused with the range named, for allow and ask boxes alike, and an ask box refuses it before any prompt. min net expose --public is its own request and is refused because this host has no public surface. The host-refusal and port prompt texts stop naming the VM host daemon, and the session e2e script pins the new out-of-range text. Backport of #2718, folded from #2729. Adapted to the line: - main's box_actor/ports.rs hunks land in session.rs. - The line has no CHANNEL_METHODS list or channel_method helper, so the net-expose-public arm joins impl SessionChannel in env.rs without a list entry, and expose_public_refused_without_public_surface drops its channel_method assertion. The refusal text and log lines it pins are unchanged. - boxes:: becomes sessions:: and BoxKeyPredicate becomes SessionKeyPredicate. (cherry picked from commit 1bbd45c)
… the host (#2721) T107. The in-VM daemon's vsock listener drops a peer at any CID but 2 at accept, before reading a byte, and writes one rate-limited audited line naming the CID (NET-139). The in-VM daemon reports each expose decision and each refused own-address egress flow over the guest door, and the VM host daemon appends them to its audit log under per-box caps, with a line counting suppressed records (NET-046). Expose decisions keep their own cap, a withdrawn box flushes its window, guest-reported records carry reported_by=guest, and box-admissions.log rotates to one kept generation at 1 MiB. The session e2e script expects the new host audit records. Backport of #2721, folded from #2735. Adapted to the line: - boxes::DynamicIngress becomes sessions::DynamicIngress. - The line has no ProxyListening verb or reply, so ReportExposeDecision, ReportRefusedEgress and Audited stand without it. - The listen watcher keeps tokio::spawn, since crate::traced is absent. The audit route is registered before the spawn and removed after the watcher's withdraw_all. - minvmd has no serde_json here, so its host audit tests parse with serde_json_lenient. - The vsock peer-CID tests join the inline tests in server.rs. Dropped: ask_audit_line_spells_box_id_as_32_hex, which reached the cherry-pick as conflict context from main's proxy work and is not part of #2721. (cherry picked from commit abe99f7)
…aken (#2352) Prerequisite for T100. A declared TCP host port that another process holds at the box's published address fails the finalize before the Active write (NET-121), with an error that names the port and the next step. The daemon probes on a native host. On a VM-backed host the forwarder binds on the host OS, so the probe is skipped and the spawn's apply reports the port. A forwarder's EADDRINUSE refusal fails the apply the same way. Backport of #2352, folded from #2738. Adapted to the line: main's box_actor/setup.rs hunk lands in session.rs, boxes::IpProto and boxes::NetworkMode become sessions::, and the fake forwarder spawns with tokio::spawn. The split from T100 carries those renames here, so this commit builds alone. (cherry picked from commit 9437ba3)
…e holds (#2725) T100. Finalize refuses a declared ingress host port that a program outside Minimal holds, or that another box holds at the 127.0.0.1 fallback once a landed range verdict keeps the box there. The typed PortInUseRefusal names the port and its holder, the daemon logs one warn line, and min session activate ends with that refusal text alone. An unknown holder is named as another program. On a VM-backed host, finalize binds the declared forwards toward the handed switch address before the Active write, and the first attach takes the host's "already bound" answer as the box's own forward. A box that finalizes at the fallback under a pending verdict gets a watcher that reports an absent landing. Backport of #2725, folded from #2738. Adapted to the line: - The finalize code lives in session.rs, not box_actor/setup.rs, and registry_name is the session module's own helper. In the CLI, activate_refusal applies to activate_session. - boxes:: becomes sessions:: and switch::BoxGate becomes switch::SessionGate. - The fallback watcher spawns with tokio::spawn under the same root span. - OwnAddressReporter::registry comes without NET-129's dynamic-hold tracking. The attach path's holder lookup needs only the accessor. - The line's DestroySessionRequest has no only_if_unfinalized, so the refusal tests assert the refused box is listed and not Active, destroy it plainly, and assert no record stays. (cherry picked from commit 703bb7f)
…ot a holder (#2754) A finalize at the shared 127.0.0.1 fallback probes each declared port with a real bind. A parallel probe of the same port held it for the moment of its own bind, so the other finalize refused the port as held by another program. The probe now binds up to three times, 20 ms apart, and names a port held only when every bind fails with EADDRINUSE. It runs on the blocking pool, and its rule takes the bind as a closure so the test fails chosen binds in turn. Adapted to the line: the box_actor/setup.rs hunk lands in session.rs, with tokio::task::spawn_blocking for crate::traced::spawn_blocking. (cherry picked from commit 8cac647)
Every own-address test box declared host port 18080. Since T100 a finalize probes a declared port at the box's published address and refuses it when something else holds it. nextest runs tests in parallel processes on one host, so tests that publish at 127.0.0.1 in lockstep can catch each other's probe and refuse each other's box. Each test process now leases one port from 23000-23999, below the kernel's ephemeral range, with a per-port lock file in a per-user directory, and every box in the test declares it, so the collision tests still put two boxes on one port. Assertions read that port back. Adapted to the line: the change lands in session/tests.rs, and boxes:: reads sessions::. Dropped: the hunks for #2749's tests, which the line does not have at this point, and for main-only test text. #2749 carries its own tests with declared_port() when it lands below. (cherry picked from commit 0be7561)
…he box range (#2332) Prerequisite for T98. Allocation drew an address out of the reserved 127.0.64.0/24 without measuring whether the host can bind it. Linux routes all of 127.0.0.0/8, but macOS answers only the addresses lo0 carries, so on a host without the range aliases the zone answered an address nothing listens at. The address book now hands a fresh box address only when switch::loopback::probe reads the whole range present, and hands the 127.0.0.1 interim otherwise. A probe refused for any reason but an absent address refuses the allocation. A box keeps its address across the probe: an interim box resumes at the interim, and a resume sends the address it was created at, so a restarted answerer hands it back. Backport of #2332, folded from #2740. Adapted to the line: the answerer imports sessions::core::zone_answer. Dropped: the edit to main's dormant-creation tests, since the line has neither those tests nor dormant rows. (cherry picked from commit 379c2f0)
…olves to (#2713) T98. A microVM daemon walked the host's loopback once, at its start, so after min finalize-install new boxes stood at the 127.0.0.1 interim until the VM restarted. The create handler on a VM-backed daemon now asks the forwarder's walk, not the guest's own lo, and every session start walks again, so a present landing moves boxes at the interim onto their range addresses and a present-to-absent walk moves them back. Walks run one at a time on the shared probe port. A held probe port counts as bound, a leftover probe forward is released before it is read, and a walk that gets no answer keeps a present verdict. The absent landing also moves the node's own address to the interim. The NET-040 spec line and the macOS e2e case come with the change. Backport of #2713, folded from #2740. Adapted to the line: - box_manager.rs and box_manager/handle.rs hunks land in sessions.rs: RangeWalk, RangeWalkSource and RangeWalkAnswer, the range_walk cell on ManagerHandle and WeakManagerHandle, session_start_range_walk and install_range_walk_standin. - rpc/tests.rs hunks land in the inline tests in rpc.rs. - crate::traced::spawn becomes tokio::spawn in the stand-in forwarders. - ADDRESS_IN_USE_BODY is shared with #2352: one copy stays in net/policy.rs. (cherry picked from commit 64d3358)
…ge lands present (#2749) Fixes a regression from T98. When a box's range probe lands present, its declared forwards, its min net expose forwards and its listen-published forwards move from the 127.0.0.1 interim to the range address, so the name and the forward answer at one address. The host egress gate admits the bounded range probe, the walk is contention-safe, and VM host-net boxes dial their listeners at the guest's 127.0.0.1. Backport of #2749. Adapted to the line: - box_actor.rs and box_actor/{handle,ports}.rs hunks land in session.rs, box_manager.rs and box_manager/handle.rs hunks in sessions.rs, and box_actor/tests.rs in session/tests.rs. The line has no box_actor/kind.rs, so its message-name hunk has no target. - crate::traced becomes tokio::spawn, and box names become session names throughout. egress_gate.rs gains the tracing::Instrument import that main already had. - ANONYMOUS_SESSION becomes pub(crate) for the actor's move log lines. - The tests' port 18080 reads declared_port(), matching #2752, which landed earlier here. - ListenPlan gains the hostnames and session_id fields the move reads. On main they came with NET-129's dynamic holds, which the line lacks; only the two fields come here. Dropped because the line has no NET-129 dynamic holds: - ListenPlan's record, release and move hold helpers, their calls in the watcher, and the bound_address helpers that fed them. A listen forward's move needs none of them: a port another box holds by declaration still stops the move, read through shared_port_holder. - The test a_listen_port_whose_move_failed_releases_its_hold_where_it_was_bound. - The dynamic-hold assertions in the runtime-publications landing test and in a_listen_port_does_not_move_onto_a_port_another_box_holds. - The host_net.insert in register_host_net: that field arrives with T106, next. (cherry picked from commit aa6964d)
…2749) Follow-up to the #2749 backport. That commit reached the branch before the group's fmt and clippy gates ran, and pushed history is not rewritten, so the correction is its own commit. ListenPlan::new now takes nine arguments, so it carries main's too_many_arguments expect, which came with NET-129 there. move_exposed_ports fits one line at the line's shorter indent. No behaviour changes.
…e proxy callers (#2716) T106. NET-141: the relay's DNS gate answers REFUSED, before any onward query, for every name outside the box zone that a declared allow_dns_hosts list does not match. It did this only for a deny-all box, so a box with a partial list still sent the name off the machine. An empty list that admits subnets keeps forwarding. Each refusal writes one rate-limited warning, keyed by a bounded hash bucket of the name. NET-070: the hostname proxy names the box behind a connection from the node's address through the socket's inode, its holder and that process's classifier leaf, and applies that box's egress rules. While a host-address box is live, a connection whose owner cannot be named is refused. Owner lookups are capped at four at once, and a wait over five seconds is refused as unattributed. session-e2e.sh asserts the partial allow list refuses fast. Backport of #2716, folded from #2755. Adapted to the line: - Box actor and box runtime hunks land in session.rs and session_host.rs. - boxes, sandbox and box_runtime read sessions, sandbox2 and session_host, with SessionPolicy and SessionKeyPredicate. crate::traced becomes tokio::spawn and tokio::task::spawn_blocking, and the line's policy has no quic443 field. - register_host_net keeps #2749's dial at the guest's 127.0.0.1 beside the host_net record. Dropped: the edi 8000 ts to the BEP steering tests in dns_gate.rs, since the line has no BEP steering, and the NET spec hunk, since the line's NET-141 text differs from main's. (cherry picked from commit 302edaf)
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
…tch ports (#2444) Prerequisite for T102. The node-plane baseline's compiled set admits by subnet alone, so once the baseline phase goes in force the gate's node-plane arm would admit frames to the switch's host alias at every port. The in-force arm now opens the alias only to TCP at the daemon's fetch port and refuses every other port and protocol as the infrastructure drop. The announced arm and every box row's verdict are untouched. The policy text and JSON views spell the alias endpoint with its bound, as 100.64.255.254/32 tcp/443. Backport of #2444. Adapted to the line: the CLI's policy view lives in cmd/session.rs, not cmd/boxes/policy.rs, and boxes:: reads sessions::. (cherry picked from commit 6471908)
Prerequisite for T102. The announced node row carries the frames of every box sharing the guest root namespace, so its reach through the host alias was admitted at every port. The alias now opens only at the host exposures, the inclusive port ranges listed in MINVMD_HOST_EXPOSURE_PORTS, read once at VM start. Unset means no exposure, and every other port is the infrastructure drop for every row. An exposure matches only a TCP or UDP frame, so an ICMP frame never opens the alias. The parser refuses port 0 and names a bad term. The VM lanes export the port their NET-003 check reaches, and add the refused-port half. T102, next, replaces this variable with the [host-exposures] table. Backport of #2331. Adapted to the line: boxes:: reads sessions:: in baseline.rs. (cherry picked from commit 0ce1fd8)
…2723) T103. The node-plane baseline ships in force. The registry and cache entries name the hosts the daemon's own fetches go to (github.com, cache.minimal.dev), and the node plane's own lookups pin the addresses they resolve to, under a box's window and cap. A frame from the node's own address reaches a pinned address at TCP 443, a subnet entry, the resolver, the host alias at a configured exposure and a resident box's lease, and nothing else. MINVMD_BASELINE_REGISTRY and MINVMD_BASELINE_CACHE re-point the entries. A host-address box sends from the node address too, so the guest classifier writes a box mark into the IPv4 DSCP field. The host gate decides a marked frame by the union of the resident host_ip boxes' rules and drops it when none is resident. The client admits a host_ip box's egress over new host-door verbs before the box runs anything, re-admits it at attach and exec, and retires it when the session goes. Backport of #2723. Lands before T102 here, as on main: T102 edits this commit's baseline and gate code, and its baseline.rs does not apply without it. Adapted to the line: - cmd/boxes/create.rs and vm_host.rs hunks land in cmd/session.rs, dash/rpc.rs in minimal-tui, and the task hunks use the line's config variable. - host_ip_box_with_vm_host and HostIpResidency live in minimal-client's box_registration, since minimal-tui is its own crate here and cannot reach minimal's. minimal-tui reads the record through a new session_record_at there, and its activation admits no declared egress because its policy is the default. - The activation's failure path has no cleanup outcome, so the guard retires on every failed finalize. Main keeps the rules when the destroy may have failed. - DropLimiter stays in egress_gate.rs, since the line has no drop_limiter module. - The line has no ProxyListening or BoxIdMinted replies, and no SessionId::mint, so tests draw their ids from a v4 UUID. boxes:: reads sessions:: throughout. (cherry picked from commit 486ea13)
…penings (#2871) T102. Behaviour change, for the release notes: host-address boxes reach only ports opened in [host-exposures]. Before this, a host-address box reached the host through host.min.internal at every port. Own-address boxes stay refused end to end: the host gate would admit a configured exposure under their rules, but the guest still refuses them. The egress gate refuses a flow to the host alias unless a port in the current [host-exposures] table of the client config.toml opens it, and the row's own rules then decide the flow. Each entry is { proto, port }, with proto defaulting to tcp. The node plane alone also reaches the ports its baseline endpoints open at the alias. minvmd rereads the table when the file changes, so an entry opens or closes its port without a restart. A missing or unparseable file fails closed. An entry at a Minimal listener's port is refused and logged. Each refused flow logs under the host-alias rule with the row and the port. This retires MINVMD_HOST_EXPOSURE_PORTS, and minvmd warns if it is still set. Backport of #2871. Lands after T103 here, as on main: its baseline and gate edits sit on that commit. T147 #2956, the project-file warning, stays out of 0.7.3. A project's [host-exposures] table still opens nothing, because the reader takes only the client file. Adapted to the line: - The client config lives in sessions/src/client/config.rs, and host_exposures joins it without main's [secrets] and [secret-store-rules] sections. - boxes:: reads sessions::, tests draw session ids from a v4 UUID, and DropLimiter stays in egress_gate.rs. (cherry picked from commit 964a71b)
…dict (#2720) T104, NET-155. A box's package builds run in the box's classifier leaf, or for an own-address box on a task network of the box's own, so the box's egress verdict decides their connections. That covers build and materialize side operations, launch builds, in-box installs, patched builds and task runs. A box whose launch placed it in a leaf refuses a build, task or check when the leaf is gone, so a build never runs outside the verdict. A build the box's rules refuse names the destination and the box, and each build start logs the box, package and leaf. A box with no leaf and no own address builds in the daemon's cgroup as node-plane traffic, as before, and logs that it does. Backport of #2720. Adapted to the line: - box_actor/setup.rs hunks land in session.rs, box_ops.rs is session_sop.rs, and the tests land in session/tests.rs, with super::setup:: read as super::, a Record literal of the line's fields, and local rewrite_record and read_record helpers. - boxes, sandbox and box_manager read sessions, sandbox2 and sessions, and crate::traced becomes tokio::spawn and tokio::task::spawn_blocking. - mctx keeps the line's build_graph body, without main's dangling-hit replan, and only gains the local_orchestrator call that carries the leaf. Dropped: main's session_id on the env channel, which T104 only carried as context, the dangling-hit test in op/src/patched.rs, and the test for #2234 in op/src/specs.rs, which comes with #2234 below. (cherry picked from commit a26f89b)
) A non-extracted Source resolves to the download cache's own file, and it was hardlinked into the build's writable /build, so a build that appended to its input changed the cached source. It is now mapped as FileCopy, as Local files already are. FileCopy no longer truncates an existing destination: copy_input_file creates with create_new, and on a collision it keeps the first file and warns, as the hardlinked File input does. Backport of #2234. Adapted to the line: the sandbox hunk lands in sandbox2, and the new test's SpecBuild names T104's classifier_leaf and box_network fields. (cherry picked from commit 13aaa43)
Task argument values were spliced into command strings unquoted, so in a single exec string
a value with spaces shattered into several argv entries, and in a bash script a value could
end the quoted region and run as shell code. A single exec string is now split into argv
words with each string value standing in as an opaque token, then each value fills its own
word, and no shell runs it. A bash script gets ${MIN_ARG_<NAME>} for each string reference,
with the value bound in the invocation's environment. The daemon and mip launch paths pass
Invocation::envs to the sandbox command. An enum value keeps its real value, since it is
validated against the author's permitted set.
Backport of #2296. Adapted to the line: sandbox:: reads sandbox2:: in mctx.
(cherry picked from commit cfcff04)
.cargo/config.toml held one thing: a [registries.buf] entry whose token line was a bearer credential in plain text. No dependency resolves through that registry, no crate names registry = "buf", and no workflow or script reads it, so the whole file goes rather than the one line. The token is still in history and needs rotating at buf.build. Backport of #2204. Applied unchanged; the line's file matched main's. (cherry picked from commit 813e4e5)
…2777) The ListSessions reply gains a map keyed by box id with the host loopback address the box's ports answer at, its effective egress posture, and whether it stands on the 127.0.0.1 fallback. All three are serde-defaulted, so an older daemon reads as unreported. min ls gains an ADDRESS column and --json carries the same facts. The EGRESS column prints the posture in the words min session policy uses, from one shared function, and the activate host line and the BOX NAMES row state how a box name opens through one resolver function. A VM node's host-address box reports no address until the node is granted one, since it is never mirrored onto 127.0.0.1. Backport of #2777. Adapted to the line: the policy.rs and create.rs hunks land in cmd/session.rs, and the minimald-rpc and minimald rpc tests land inline in lib.rs and rpc.rs, with the line's names (SessionStatus, EffectiveSessionPolicy, a built CreateSessionRequest). (cherry picked from commit 08045bf)
… net forward (#2626) NET-058 says a box name alone decides which VM a verb looks in, and attach honours it: the selected VM's daemon first, then every VM's socket. min session exec, min session run and min net forward still looked only in the selected VM, so a box activated with --vm was listed by min ls and reachable by attach, and exec answered "No session found matching". The three now go through the resolution attach uses, generalised by the verb that leads its one announcing line, and the hand-off runs over the owning VM's socket. NET-058 names the verbs it now covers. Backport of #2626. Adapted to the line: the cmd/boxes/attach.rs change lands in cmd/session.rs, with the line's session_announce names. (cherry picked from commit f2e6ed6)
There was a problem hiding this comment.
Review of b568f8d, triaged for a backport. I checked each finding below against this head and against main. All of them are on main too, so I do not suggest changing this branch's commits. Fix on main, then cherry-pick per release-ops#7.
Worth deciding before 0.7.3 ships (NET-155 enforcement)
- An in-box
min patched-pkgruns outside the box's egress leaf.crates/mctx/src/env.rs:268-271(EnvChannel::run_patched_pkg) passesclassifier_leaf: None, box_network: None. The comment says "a client-side patched build runs for no box", but a daemon task exec builds its env through this channel:minimald/src/exec.rs:483→make_env_with_network→EnvChannelatmctx/src/env.rs:1172. That task context does carry the leaf (exec.rs:414refuses without it), andcloned_reinitcopies it intobuild_ctx. So in a deny-all task box, a patched build's downloads run in the daemon's cgroup and are not refused.min install/min runin the same box are refused. The daemon's own patched path (minimald/src/env.rs:1388) already passes the leaf. Fix:classifier_leaf: build_ctx.classifier_leaf().cloned(), plusbox_networkthe wayminimald/src/env.rs:1395picks it. Same code on main. - A failed
host_ipadmit is silent.HostIpResidency::admitreturnsNoneon a failed or unanswered exchange. That isbox_registration.rs:822here andcmd/boxes/vm_host.rson main. The activation then succeeds with only atracing::warn. On a current VM host that timed out, the gate drops every frame the box sends (HostIpUnbounded), and nothing the user sees says why. An older daemon is fine, because its gate does not enforce. This is not a code bug, but a box with no network and no explanation is a support case. At least a line on the start, or amin ls/min box showstate, would help. Same on main.
Follow-up on main, not this backport
- Rule union across resident
host_ipboxes (minvmd/src/box_registry.rshost_ip_verdict, and the shared cohort pin record). A deny-allhost_ipbox can reach a name that another resident box allows and resolved. The admit's log line says the union is intentional, so this is a design question, not a porting bug. I will file it as an issue on main. - The attribution semaphore (
minimald/src/net/proxy.rs:356): 4 slots with a 5 s wait, then a 403 "cannot tell which box opened this connection". Under parallel host-side connections, that refuses traffic NET-071 lets through. Check whether it is new in this backport. - The NET-155 refusal line rarely prints (
minimald/src/env.rs:2435).patched_build_refusalneeds the build's error string to contain the refused host, but that string is usually only "exit status N".
Notes only
host_ip_box_at(attach.rs:568) takes anyHostIpBox { .. }reply as success. Todayadmit_host_ip_boxalways answersresident: truewith the request's id, so this cannot trigger now. Checkingresident && session_id == idis cheap hardening.HostIpResidency::drop(box_registration.rs:851) does a blocking control exchange on a tokio worker. That happens only on a failure path.- Destroy sends RetireHostIpBox for boxes that never admitted (
cmd/session.rs:245). Gating it onHostNetsaves a round-trip when the VM host is down. task_producerreads the box record twice (exec.rs:455).
Checked and dropped: an own-address box always gets its build network (own_address_build_network returns Some for every OwnIp box, built lazily), so task_build_refusal not covering it is fine.
Policy and destroy resolve a box's VM from its name, as attach, exec, run and net forward do. A box no running VM holds names --vm, a box on a stopped VM names the command that starts it, and a name any two VMs hold, running or stopped, is refused with every VM listed. A relay failure writes the unwind before the attach error prints, so the error stays on screen. Backport of #2811. Adapted to the line: cmd/boxes/attach.rs and policy.rs hunks land in cmd/session.rs. Dropped, because the line has no stopped session status (#2676) and keeps box ids apart from session ids (#2485): min ls rows for a stopped VM's boxes, vm_running in its JSON, and id-prefix matching against a stopped VM's records, which match by name only here. (cherry picked from commit 2e3962f)
…ine (#2303) russh bounds every session-loop transport write only by the inactivity timer, and minimald set it to None, so a write that never completed parked the session loop forever. Keepalives are dispatched from that same loop, so they stopped firing too: an attach whose transport wedged went dark in both directions and survived every keepalive budget. The timer is now armed one interval past the keepalive budget, so a healthy idle attach is never reaped and a wedged one is torn down. Backport of #2303. Adapted to the line: the test module gains the small accept-all client handler main's connection tests already had. (cherry picked from commit 02f3af9)
…rename (#2242) FileCache::write_through created the content-addressed file in place and streamed into it. A stream error left partial bytes under the pinned hash, and a concurrent fetcher could read the truncated file while the download was in flight. It now streams into a uniquely named temp file in the same sha directory, fsyncs it, verifies the SHA-256, and only then renames it onto the final path. The temp file goes on every error path, and a write error returns an I/O error instead of panicking. A failed fsync of the directory warns and does not fail the download. Backport of #2242. Applied without adaptation. (cherry picked from commit 40420c9)
…2319) The post-receive hook checked out every pushed branch, so pushing a branch other than the workspace's current one moved HEAD and swapped the worktree to it. A push to a non-checked-out branch now only moves the ref. A first push into a fresh workspace checks out the first branch and leaves the rest as refs, and a push onto a detached HEAD says so on a remote: line with the git switch that re-attaches it. The cli-min push paragraph describes all three. Backport of #2319. Applied without adaptation. (cherry picked from commit 0a297d0)
…#2572) hakoniwa arms PR_SET_PDEATHSIG(SIGKILL) in every container it forks, and Linux delivers that signal when the forking thread exits. The task-run path in exec.rs forked its container on whichever tokio worker ran the exec. Any block_in_place on that worker displaces it, tokio retires it after its 10 s keep-alive, and every idle task session forked on it dies with exit 125. The spawn now goes through on_fork_thread, as the session launch and run_with_cancel do. Backport of #2572. Adapted to the line: sandbox:: reads sandbox2::. (cherry picked from commit cafa674)
…2342) An uninstall deleted the binaries but left a running daemon in place, so a reinstall autospawned nothing and every daemon-backed command then hit the old daemon across a version skew. The uninstall walk now stops the daemon first, while the min that matches it is still on disk, with the same escalation as an upgrade. An install that starts with no min on disk compares the installed min's version with the answering daemon's and force-stops a mismatched one. The dashboard's discovery connections are now gated as min ls is, so it refuses a skewed daemon before the TUI takes the terminal, and a provider that reappears skewed joins only under the override. The skew message's recovery line names min stop --force. Backport of #2342. Adapted to the line: dash/ is the minimal-tui crate, so its inventory test carries the gated rows, and the rows in minimal's connection inventory drop out. (cherry picked from commit 2e67f8a)
…2338) A client attached during an upgrade autospawns a replacement daemon the moment the pre-swap stop ends, and that daemon serves the old version from the binaries the run is about to replace. The installer now stops once more after every swap, only a daemon whose version differs from the installed min, and --force only with consent. A pre-swap yes covers only the sessions it listed: sessions opened after it are asked about again, and with no terminal the daemon stays running and the installer names min stop --force. An EXIT trap runs the same stop when the run dies after the first executable swap. Spec 07 R5.5 describes it. Backport of #2338. Applied without adaptation, after #2342 as on main. (cherry picked from commit e6cbd46)
…start (#2298) A minvmd load reinstated each standing row detached, arming the 45 s detach grace. A VM's cold boot outlasts that, so the row, and with it the box's published name and declared ingress, was gone before the guest daemon started. Reloaded rows now wait under the resume bound. The guest resume also started a restored box's actor but never its host, so its shuttle never attached and ingress stayed unbound until a client's first exec or attach. Resume now launches an own-address box's host detached from the resume, and the attach announces the box's lease, so an idle box carries its row. Backport of #2298. Adapted to the line: box_actor and box_manager hunks land in session/tests.rs and sessions.rs, crate::traced::spawn_detached becomes an instrumented tokio::spawn, and line names replace BoxGate, BoxKeyPredicate and boxes::. #2333 below moves the announcement. (cherry picked from commit 10d34a5)
A gated attach wrote its framed gratuitous ARP into the /connect handshake, before the relay owned the stream. gvproxy's hijack discards bytes already buffered, so the ARP's tail was read as a bogus length prefix and box ingress died. The handshake now speaks only the upgrade, and the relay sends the announcement as its first frame, one short delay after it starts. Only the vsock attach announces: on the local-socket attach the tap wears a kernel-chosen MAC, so the announcement would point the gateway at a MAC the box does not wear, and there is no host-side row for it to carry. Backport of #2333. Required follow-up to #2298. Adapted to the line: crate::traced::spawn reads tokio::spawn, and line names replace BoxGate and boxes::. (cherry picked from commit 1bec117)
|
Reviewed: 2 findings, none blocking at Address the comments on the diff. Clobber: was not checked in depth. If that was not intentional, restore the earlier change. |
The release run stages the version that package.version declares, and a staged version is permanent. A candidate number keeps 0.7.3 free for the final build.
A macOS VM host prints "this VM's host daemon answers its box names on 127.0.0.1:<port> (UDP)", so the parser in fresh_install_range_lands_on_macos found no port and failed the lane. This takes the one line from #2741 (de32bd3). The rest of that commit stays off the 0.7 line. The case now matches main.
| [registries.buf] | ||
| index = "sparse+https://buf.build/gen/cargo/" | ||
| credential-provider = "cargo:token" | ||
| token = "Bearer c5ceab0fe4fbdddabe0aefb73a1351aa7f77149a9df3837af3f27e4f4171119f" |
There was a problem hiding this comment.
MEDIUM · security · confidence 0.55
This PR deletes a committed buf registry bearer token. The token stays in the history of release/0.7.x and in every published 0.7.x tag. Deleting the file does not revoke it. Confirm that the token was rotated when #2204 landed on main. If it was not, revoke it now.
What the reviewer checked
-token = "Bearer c5ceab0f..." in .cargo/config.toml
Hand this to an agent
Act on a code-review finding.
File: .cargo/config.toml
Lines: 1-4 (in the pre-change version of the file)
Category: security
Severity: medium (reviewer confidence 0.55)
Finding:
This PR deletes a committed buf registry bearer token. The token stays in the history of release/0.7.x and in every published 0.7.x tag. Deleting the file does not revoke it. Confirm that the token was rotated when #2204 landed on main. If it was not, revoke it now.
First verify this against the code yourself. It is model output and
may be wrong. If it is wrong, or the tradeoff was deliberate, say so
and change nothing.
👍 useful · 👎 noise — react to tell the reviewer. Replying works too, and says more.
| { | ||
| Ok(f) => f, | ||
| Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => return Ok(false), | ||
| Err(e) => return Err(e), | ||
| }; | ||
| let mut input = fs::File::open(src)?; | ||
| std::io::copy(&mut input, &mut out)?; | ||
| out.set_permissions(input.metadata()?.permissions())?; | ||
| Ok(true) |
There was a problem hiding this comment.
LOW · correctness · confidence 0.50 · in copy_input_file
copy_input_file creates dest with create_new before it opens src. If the src open or the copy fails, an empty or partial dest stays in the sandbox dir. The caller returns an error, so the sandbox is dropped. A retry that reuses the dir would see AlreadyExists and skip the copy. Open src first.
What the reviewer checked
let mut out = ...create_new(true).open(dest)...; let mut input = fs::File::open(src)?;
Hand this to an agent
Act on a code-review finding.
File: crates/sandbox2/src/lib.rs
Lines: 2758-2766
Category: correctness
Severity: low (reviewer confidence 0.50)
Finding:
`copy_input_file` creates `dest` with `create_new` before it opens `src`. If the `src` open or the copy fails, an empty or partial `dest` stays in the sandbox dir. The caller returns an error, so the sandbox is dropped. A retry that reuses the dir would see `AlreadyExists` and skip the copy. Open `src` first.
First verify this against the code yourself. It is model output and
may be wrong. If it is wrong, or the tradeoff was deliberate, say so
and change nothing.
👍 useful · 👎 noise — react to tell the reviewer. Replying works too, and says more.
Backports the 0.7.3 list onto
release/0.7.x, one commit per item, in the list's order except where the table says otherwise. The list and porting rules are in https://github.com/gominimal/release-ops/issues/7.This PR must land with Rebase and merge, so each commit reaches the line as is.
8c4bcd6d2sets the version to 0.7.3-rc1. The commit after it,38c080199, is a one-line e2e parser fix from #2741: the macOS lane failed without it. Every other subject isfix(...), ortest(...)for a test-only item.fbe342a8etokio::spawn; keeps the withdrawn-port test from #2732, without a dynamic hold950f384aasession.rs; nochannel_methodlist or assertion47df1d656ProxyListening;serde_json_lenientin minvmd tests; server tests inline inserver.rs403d8e83dsetup.rshunk insession.rs; renames carried here so it builds alonee289e5fd2session.rs;registry()accessor only; tests adapted for noonly_if_unfinalizedc7087f000setup.rshunk insession.rs;tokio::task::spawn_blocking027dfe61csession/tests.rs; hunks for #2749 tests dropped here, since #2749 lands later on this branch7981f0e2c947b955fdsessions.rsand inlinerpc.rstests; oneADDRESS_IN_USE_BODYc36cd6e2asession.rsandsessions.rs;ListenPlangainshostnamesandsession_id; NET-129 dynamic-hold code, one test and hold assertions dropped; test ports usedeclared_port()8acbf4d068746a3c7fregister_host_netkeeps #2749's dial7302e78d4cmd/session.rs; line names7299c15edbaseline.rs55163d675host_ip_box_with_vm_hostandHostIpResidencylive inminimal-client, sinceminimal-tuiis its own crate here. The guard retires on every failed finalize.DropLimiterstays inegress_gate.rs5dddc5e43[host-exposures]. Own-address boxes stay refused end to end. [#2956](#2956) stays out, so a project's[host-exposures]table opens nothing. Config lands insessions/src/client/config.rs, without main's[secrets]sectionsec7524af0box_actor/setup.rslands insession.rs;tokio::spawnforcrate::traced;mctxkeeps the line'sbuild_graphbody; droppedsession_idon the env channel and the dangling-hit testb568f8daesandbox2; the test names T104's fieldsfd35986desandbox::readssandbox2::inmctxcb85e78e6Cargo.lockonly. Clears thecargo-denyfailure, RUSTSEC-2026-043382c8fe7600ce56e4f3policy.rsandcreate.rshunks land incmd/session.rs; RPC tests inline inlib.rsandrpc.rs; line names93dd243a3cmd/boxes/attach.rschange lands incmd/session.rs91d492a27cmd/boxeshunks land incmd/session.rs. Dropped:min lsrows for a stopped VM's boxes,vm_runningin its JSON and the(stopped)VM cell, because the line has no stopped status ([#2676](#2676)) and keeps box ids apart from session ids ([#2485](#2485)). Stopped VMs match by name only, never by id prefix. Thels_lists_boxes_on_stopped_vmtest and aStopBoxtest arm go with them14c0e8a8d3d4e6ee1816970444294eb0ebe6sandbox::readssandbox2::e34798455dash/is theminimal-tuicrate, so its own inventory test carries the gated rowsaeaf53cf92b8ead991box_actorandbox_managerhunks land insession/tests.rsandsessions.rs;crate::traced::spawn_detachedbecomes an instrumentedtokio::spawn; line names89a676d3ecrate::traced::spawnreadstokio::spawn; line names8c4bcd6d2package.versionto0.7.3-rc1inCargo.tomland the 8 workspace entries inCargo.lock. No other changesReviewers: please check
egress_gate.rsrange-probe admission came over with renames only. They arrived with #2749 and were not adapted further, so they need a read against the line.Status
The list is ported. T112 #2832 is left out of 0.7.3: its reclaim needs the gate ledger from #2776. A proxy that starts on a substitute port stays there until the VM restarts.
#3004 has not merged on main, so it is not here.
This stages 0.7.3-rc1. The final release needs one more PR that sets
package.versionto0.7.3.Local verification
Run in the Lima VM through
just, at8c4bcd6d2:just fmt-check,just clippy,cargo check --workspace --all-targets --locked,just check-version(it accepts0.7.3-rc1) andjust denypass.just test-installer(850 checks) passed at89a676d3e, the commit before.just testruns 3929 tests: 3925 pass and 4 fail. Those 4 are known to fail only in the VM:a_hook_launch_does_not_advise_unenforced_placementand threefinalize_install_undo_removes_*tests.Each commit from #2444 on passed
just fmt-check,just clippyandjust test, with the same 4 failures, before it was pushed.The VM lanes, the session e2e script, root integration and macOS were not run locally, so CI is their first run.