mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 18:54:03 +01:00
The bind-mount logic goes to hosts_mount.sh, the Magisk-module and
cache-invalidation logic to hosts_magisk.sh. Both flat siblings, both in
both deploy lists; the two lists were then checked to correspond exactly
in both directions, since a push with no matching cp stages a file that
never lands and the enforcer would fail to source it.
Audited for stdin-draining `while read` loops BEFORE extracting, because
piping one would change behaviour in a way stubs cannot catch. There are
none here. Also confirmed no function writes a global, so there was no
cross-half hazard of the kind that kept NET_BUILT in curfew_enforcer.sh.
69 assertions, 43/43 and 62/62 lines, 17 mutations all killed. Two survived
the first run and both were real findings:
- the unmount give-up threshold was not pinned. Raising it from 5 to 500
changed nothing observable, so the enforcer could have spun 500 times
per poll against a mount that was never going to clear. Now asserted as
a call count.
- the `[ ! -f $HOSTS_TARGET ] && return 1` guard in
is_bind_mounted_correctly is PROVABLY EQUIVALENT: sha256_of returns
empty for a missing file, so the existing -n check already rejects that
case. No test can distinguish it. Equivalent code is a claim of a check
that is not being made, so it is deleted rather than covered by a test
that would pass either way. Old and new bodies were compared across all
four input states -- both-missing, target-missing, match, mismatch --
and agree on every one.
That deletion is the only non-verbatim function; the other 19 moved
untouched, making this the first fully verbatim extraction of the session.
Ordering is asserted where it is load-bearing: /system must go back to ro
after rw, and +i must be restored after being dropped. Presence assertions
alone would pass with either pair reversed.
UNVERIFIED ON DEVICE -- the highest-stakes of the four enforcer splits now
outstanding, since a failure to source leaves nothing blocking while the
phone looks normal. Over-cap count 20 -> 19.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
82 lines
7.5 KiB
JSON
82 lines
7.5 KiB
JSON
{
|
|
"intent": "Bring hosts_enforcer.sh under the 250-line cap by extracting its bind-mount and Magisk/cache halves into two flat siblings, and cover both at 100% — neither had any test, and together they decide whether the DNS blocklist is actually in force.",
|
|
"scope": [
|
|
"phone_focus_mode/hosts_enforcer.sh - 421 lines down to 207",
|
|
"phone_focus_mode/hosts_mount.sh - new: is_bind_mounted_correctly, unmount_existing_hosts_mount, make_target_writable_once, assert_bind_mount",
|
|
"phone_focus_mode/hosts_magisk.sh - new: sync_magisk_module, protect_magisk_module, disable_firefox_doh, flush_browser_dns_caches, ensure_canonical_immutable, restart_netd_for_hosts_cache",
|
|
"phone_focus_mode/deploy.sh - both siblings added to both hardcoded lists",
|
|
"phone_focus_mode/lib/tests/ - a harness, four case files and one entry point, all new",
|
|
"Non-goal: any device deploy. The split is proven with stubs, hashes and behavioural comparison instead."
|
|
],
|
|
"changes": [
|
|
"Audited for stdin-draining loops BEFORE extracting, because piping such a loop would silently change behaviour in a way the stubs cannot catch. hosts_enforcer.sh contains no `while read` loop at all, so that risk did not apply here. Also checked that no function writes a global, so there was no cross-half read/write hazard of the kind that kept NET_BUILT in the curfew entry script.",
|
|
"Placed both libraries as flat siblings, matching dns_iptables.sh, tether_iptables.sh and curfew_net.sh: deploy.sh pushes phone scripts into one directory, so a lib/ path would not exist on the device.",
|
|
"Added both to deploy.sh's push list and cp list, then verified the two lists correspond exactly with no orphan in either direction — a push without a matching cp stages a file that never lands, and the enforcer would then fail to source it.",
|
|
"Removed a provably equivalent guard from is_bind_mounted_correctly. Its early `[ ! -f $HOSTS_TARGET ] && return 1` is unreachable as a decision: sha256_of returns empty for a missing file, so the existing -n check already rejects that case. A mutation removing it survived because no test could distinguish it. Equivalent code is a claim of a check that is not being made, so it was deleted rather than papered over with a test that would pass either way.",
|
|
"Stubbed cp, chattr, mount, umount, am, pgrep, stop, start and sleep on PATH — the process boundary, since these libraries invoke real binaries. Two hardcoded paths cannot be stubbed that way (/proc/self/mounts and the Fenix profile glob), so the staged copies have those substituted for harness-controlled directories while the shipped files keep their literal paths.",
|
|
"The harness needs a copy the cp stub cannot intercept, so it uses shell redirection, which is a builtin and cannot be shadowed. The mount stub had the same problem and the same fix."
|
|
],
|
|
"verification": [
|
|
{
|
|
"command": "bash phone_focus_mode/lib/tests/test_hosts_libs.sh",
|
|
"result": "pass",
|
|
"evidence": "Results: 69 passed, 0 failed. Neither library had a test before."
|
|
},
|
|
{
|
|
"command": "bash meta/scripts/shell_coverage.sh phone_focus_mode/lib/tests/test_hosts_libs.sh hosts_mount.sh",
|
|
"result": "pass",
|
|
"evidence": "hosts_mount.sh: 43/43 lines = 100.00%, exit 0 at the default minimum. First measured run was 91.11%."
|
|
},
|
|
{
|
|
"command": "bash meta/scripts/shell_coverage.sh phone_focus_mode/lib/tests/test_hosts_libs.sh hosts_magisk.sh",
|
|
"result": "pass",
|
|
"evidence": "hosts_magisk.sh: 62/62 lines = 100.00%. First measured run was 83.87%."
|
|
},
|
|
{
|
|
"command": "mutation run: 17 mutations of the mount and magisk behaviour",
|
|
"result": "pass",
|
|
"evidence": "17 killed, 0 survived. Two survived the first run and both were real: the unmount give-up threshold was not pinned to 5 attempts (raising it to 500 changed nothing observable), and the missing-target case was masked. The first was closed with an attempt-count assertion; the second turned out to be equivalent code and was deleted."
|
|
},
|
|
{
|
|
"command": "ordering assertions inside the suite",
|
|
"result": "pass",
|
|
"evidence": "make_target_writable_once is asserted to remount /system ro AFTER rw and to re-set +i AFTER dropping it. Presence assertions alone would pass with either pair reversed, which would leave /system writable or the hosts file unlocked."
|
|
},
|
|
{
|
|
"command": "bash meta/scripts/verify_shell_split.sh 9f2e208 phone_focus_mode/hosts_enforcer.sh phone_focus_mode/hosts_enforcer.sh phone_focus_mode/hosts_magisk.sh phone_focus_mode/hosts_mount.sh",
|
|
"result": "pass",
|
|
"evidence": "Reports only is_bind_mounted_correctly as differing — the function whose equivalent guard was removed. All 19 other functions hash identical, so this is the first split in this session where the extraction itself was fully verbatim."
|
|
},
|
|
{
|
|
"command": "behavioural comparison of is_bind_mounted_correctly, old body vs new, across every input state",
|
|
"result": "pass",
|
|
"evidence": "both-missing NOT / target-missing NOT / match MOUNTED / mismatch NOT — identical from both bodies. The hash difference carries no behaviour change."
|
|
},
|
|
{
|
|
"command": "shellcheck on each touched file individually (no -x); sh -n on the three phone-side scripts",
|
|
"result": "pass",
|
|
"evidence": "All eleven files clean standalone. Two SC2034 findings were resolved by deleting globals the harness defined but nothing read, not by a disable. All three phone scripts parse under ash, which is what runs them on the device."
|
|
},
|
|
{
|
|
"command": "deploy-list parity check in both directions",
|
|
"result": "pass",
|
|
"evidence": "comm over the push list and the cp list returns empty both ways: every pushed file has a matching cp, and every cp has a matching push. hosts_magisk.sh and hosts_mount.sh appear in both."
|
|
},
|
|
{
|
|
"command": "bash meta/scripts/check_file_length.sh --all",
|
|
"result": "pass",
|
|
"evidence": "19 over-cap files, down from 20. hosts_enforcer.sh 207, hosts_mount.sh 91, hosts_magisk.sh 166, and the six test files between 24 and 198 — all under the cap."
|
|
}
|
|
],
|
|
"risks": [
|
|
"UNVERIFIED ON DEVICE. This is the third enforcer split in this session without a deploy behind it, after tether_enforcer.sh, dns_enforcer.sh and curfew_enforcer.sh. hosts_enforcer.sh is the highest-stakes of them: if it fails to source a sibling it exits, and nothing is blocking while the phone looks normal.",
|
|
"Two new files must reach the device. A stale checkout or a partial push leaves hosts_enforcer.sh unable to source them, which stops the enforcer outright rather than degrading it.",
|
|
"The tests substitute two hardcoded paths in the staged copies (/proc/self/mounts and the Fenix profile glob). If either path changes in the shipped file without the harness's sed being updated, the substitution silently stops matching and those tests would exercise the real paths — which do not exist here, so the cases would pass vacuously. The mutation run is what would catch that."
|
|
],
|
|
"rollback": [
|
|
"git revert the commit. hosts_enforcer.sh returns to a single 421-line file, over the cap and untested, and deploy.sh stops pushing the two siblings.",
|
|
"After rollback, run sh -n phone_focus_mode/hosts_enforcer.sh expecting exit 0, and confirm grep -c 'hosts_magisk\\|hosts_mount' phone_focus_mode/deploy.sh returns 0.",
|
|
"A rollback AFTER a deploy leaves two stale files in $REMOTE_DIR. They are inert once nothing sources them, but remove them to keep a later audit honest."
|
|
]
|
|
}
|