app
SOLIDWORKS Bridge
Public Made by Adomby adom
Launch, model and quit SOLIDWORKS from any Adom container. Nothing is ever lost.
main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
//! ADVERSARIAL REVIEW OF 0.6.1 — pass fourteen.
//!
//! NO CONFIRMED FINDINGS. 0.6.1's re-attribution now runs on every `report`, so
//! the question is whether a status read can flip a user's session to ours. It
//! cannot on timing alone: a POSITIVE lineage link is required, and both proofs
//! fail closed once our chain is dead — `log_authored_by_our_chain` needs
//! `thread_owner(tid)`, which needs the writer's process ALIVE, and the parent
//! walk needs a live census entry to start from.
//!
//! THIS PIN CANNOT CURRENTLY BE SATISFIED, and that is the finding. It fails on
//! its own precondition, because `foreign_chain_seen` latches on OUR OWN
//! launcher (see the second test) and `reattribute_after_attach` bails on that
//! flag before it consults lineage at all. So the lineage proof — the whole
//! point of 0.6.1 and 0.6.2's hardening of it — is unreachable on an ordinary
//! run, and neither the Builder's tests nor my earlier pass-14 pin ever
//! exercised it. Fix the flag and this pin starts testing what it says.
mod common;
use common::{Bridge, TempDir};
use serde_json::{json, Value};
use swx_bridge::launchos::FakeOs;
fn s(v: &Value) -> String {
serde_json::to_string_pretty(v).unwrap_or_default()
}
/// Our route reaches `Run Begin` and dies without producing SOLIDWORKS — the
/// shape 0.5.9 mis-handled. The user then starts their own, which is newer than
/// our invoke and descends from THEIR launcher. Re-attribution must refuse, and
/// must keep refusing on every subsequent read (no flip-flop).
#[test]
fn a_session_with_no_lineage_link_is_never_adopted_however_often_status_is_read() {
let dir = TempDir::new("adv14-lineage");
std::fs::write(
dir.join("routes.json"),
// ONE route only, and it ends in `sldworksUpNotAttached` (Run Begin,
// a SOLIDWORKS appears, COM never attaches) so the ladder STOPS after
// it. That matters: on a multi-route attempt `foreignChainSeen` latches
// true and `reattribute_after_attach` bails on THAT before lineage is
// ever consulted — which is how an earlier version of this pin passed
// without exercising the lineage proof at all.
json!({"shellExecute": {"chain": true, "runBeginAfterMs": 0, "sldworksAfterMs": 0}})
.to_string(),
)
.unwrap();
std::fs::write(dir.join("preexisting.json"), json!([]).to_string()).unwrap();
// The user's SOLIDWORKS descends from a launcher that was never ours.
std::fs::write(dir.join("sldworks-parent"), "4242").unwrap();
let lnk = format!("{}/SOLIDWORKS Design.lnk", dir.path());
std::fs::write(&lnk, "x").unwrap();
let b = Bridge::start_in(
TempDir::new("adv14-scratch"),
&[
("SWX_SOLIDWORKS_SHORTCUT", &lnk),
("SWX_LAUNCH_FAKE_DIR", &dir.path()),
("SWX_LAUNCH_RUN_BEGIN_SECS", "1"),
("SWX_LAUNCH_SLDWORKS_SECS", "2"),
("SWX_LAUNCH_ATTACH_SECS", "3"),
("SWX_LAUNCH_POLL_MS", "100"),
("SWX_LAUNCH_RETRY_SETTLE_MS", "400"),
("SWX_LAUNCH_BACKOFF_SECS", "0"),
],
);
b.call("swx_start", json!({"reason": "starting SOLIDWORKS", "waitSeconds": 0}));
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(40);
loop {
let st = b.call("swx_status", json!({}));
if st["launch"]["finished"] == true || std::time::Instant::now() > deadline {
break;
}
std::thread::sleep(std::time::Duration::from_millis(200));
}
// NOT VACUOUS: re-attribution must actually be REACHABLE here, so every
// guard ahead of the lineage proof has to be satisfied first.
let pre = b.call("swx_status", json!({}));
assert!(
pre["launch"]["finished"] == true
&& pre["launch"]["outcome"] != "attached"
&& pre["launch"]["foreignChainSeen"] != true,
"precondition: a finished, un-attached attempt with NO foreign chain seen, so lineage is \
the guard under test rather than foreignChainSeen: {}",
s(&pre["launch"])
);
assert!(
pre["launch"]["routesTried"]
.as_array()
.map(|a| a.iter().any(|t| t["runBeginSeen"] == true))
.unwrap_or(false),
"precondition: a route of ours reached Run Begin, so `proven` resolves: {}",
s(&pre["launch"])
);
assert!(
pre["solidworks"]["processId"].is_number(),
"precondition: a SOLIDWORKS is in the census for the lineage walk to start from: {}",
s(&pre["solidworks"])
);
// EVERY read, not just the first: re-attribution runs on every report now,
// so a property that holds once must hold repeatedly.
for i in 1..=5 {
std::thread::sleep(std::time::Duration::from_millis(200));
let st = b.call("swx_status", json!({}));
let outcome = st["launch"]["outcome"].as_str().unwrap_or("").to_string();
assert_ne!(
outcome, "attachedAfterSignIn",
"read {i}: the bridge adopted a SOLIDWORKS the USER started. It is newer than our \
invoke, but it descends from a launcher that was never ours — timing plus the \
ABSENCE of a foreign-chain observation is not a lineage proof.\n{}\n\
--- server log ---\n{}",
s(&st["launch"]),
b.log()
);
}
}
/// OUR OWN LAUNCHER IS COUNTED AS A FOREIGN CHAIN.
///
/// `watch_route` asks, on each census, whether any terminable process is
/// "not ours, not in the baseline, not the attribution root" — and it asks it
/// BEFORE `attributed_chain` records the chain in the same iteration. On the
/// first census after an invoke, `chain_pids_now()` is still empty (the chain is
/// cleared at the top of each route) and the only pid excluded by name is the
/// attribution ROOT, the CATSTART. `SWXDesktopLauncher.exe` — the root's own
/// child, the second half of the chain we just started — matches every clause
/// and latches `foreign_chain_seen`.
///
/// The fixture below contains NO other launcher chain: `preexisting.json` is
/// empty and one route runs once, so every terminable process in that census is
/// ours by construction. A `foreignChainSeen: true` here can only be our own.
///
/// It matters because `reattribute_after_attach` bails on `foreign_chain_seen`
/// before it consults lineage at all. So the sign-in recovery that 0.6.1 added
/// and 0.6.2 hardened is unreachable on an ordinary run — which is also why both
/// the Builder's case-collision tests and my own pass-14 pin passed without ever
/// exercising the lineage proof.
#[test]
fn our_own_launcher_is_not_a_foreign_chain() {
let dir = TempDir::new("adv14-selfforeign");
std::fs::write(
dir.join("routes.json"),
json!({"shellExecute": {"chain": true, "runBeginAfterMs": 0, "sldworksAfterMs": 0}})
.to_string(),
)
.unwrap();
// NOTHING else on the machine: no daemons, no other chain.
std::fs::write(dir.join("preexisting.json"), json!([]).to_string()).unwrap();
let lnk = format!("{}/SOLIDWORKS Design.lnk", dir.path());
std::fs::write(&lnk, "x").unwrap();
let b = Bridge::start_in(
TempDir::new("adv14-scratch2"),
&[
("SWX_SOLIDWORKS_SHORTCUT", &lnk),
("SWX_LAUNCH_FAKE_DIR", &dir.path()),
("SWX_LAUNCH_RUN_BEGIN_SECS", "1"),
("SWX_LAUNCH_SLDWORKS_SECS", "2"),
("SWX_LAUNCH_ATTACH_SECS", "3"),
("SWX_LAUNCH_POLL_MS", "100"),
("SWX_LAUNCH_RETRY_SETTLE_MS", "400"),
("SWX_LAUNCH_BACKOFF_SECS", "0"),
],
);
b.call("swx_start", json!({"reason": "starting SOLIDWORKS", "waitSeconds": 0}));
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(40);
loop {
let st = b.call("swx_status", json!({}));
if st["launch"]["finished"] == true || std::time::Instant::now() > deadline {
break;
}
std::thread::sleep(std::time::Duration::from_millis(200));
}
let st = b.call("swx_status", json!({}));
let chain: Vec<u64> = st["launch"]["chainPids"]
.as_array()
.map(|a| a.iter().filter_map(|p| p["pid"].as_u64()).collect())
.unwrap_or_default();
assert!(
st["launch"]["foreignChainSeen"] != true,
"the attempt recorded a FOREIGN chain on a machine whose only launcher processes are the \
ones it started itself (chainPids {chain:?}, preexisting empty, one route). The check \
runs before `attributed_chain` records the chain, so our own SWXDesktopLauncher — the \
attribution root's own child — matches 'not ours, not baseline, not the root'. \
`reattribute_after_attach` bails on this flag before it ever reaches the lineage proof, \
so sign-in recovery is unreachable on an ordinary run.\n{}\n--- server log ---\n{}",
s(&st["launch"]),
b.log()
);
}