main
Drew Owens 0.11.2 source 784acbf 5d ago
//! 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()
    );
}