mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 16:34:06 +01:00
nc_php.sh was the next-hardest library on the allowlist. It targets a Debian Raspberry Pi -- it edits /etc/php/<ver>/apache2/php.ini, drives occ as www-data and installs a crontab -- so none of its write targets exist on this Arch host and the jail had nothing to mirror. - --seed-dir / --seed-file create the paths a foreign-platform subject expects. Verified with a probe: /etc/php/8.2/apache2 exists inside the jail while /etc/php does not exist outside it. - A failed bind is now FATAL, and missing mountpoints are created first. A bind that fails silently is indistinguishable from unreachable code in the report, which is the misdiagnosis this runner exists to prevent. - Mirroring skips unreadable targets (/root as a normal user) rather than aborting under set -e. nc_php.sh: 84/85 = 98.82%, 24 assertions. It STAYS on the allowlist, because 98.82% is below the bar. Line 111 -- the crontab first-run fallback -- hung the suite on both attempts to cover it, so it is left uncovered and documented rather than tried a third time. Two harness hazards found the hard way and written down: a top-level stub function shadows the subject's own function for every later assertion (this silently dropped coverage 83.53% -> 57.65% while the tests still passed), and a stub for a piped-into command must drain stdin or the writer takes SIGPIPE. dot_resolver_install.sh still measures 39/39 = 100.00%. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DbD4nco3EgL1UFoZKmKsLE
110 lines
4.3 KiB
Bash
Executable File
110 lines
4.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# ============================================================================
|
|
# Jail construction for shell_coverage_jail.sh.
|
|
#
|
|
# Split out on 2026-08-22 to hold both files under the repo's 250-line cap
|
|
# (shfmt's reformatting pushed the combined file to 289). Sourced, not
|
|
# executed: every function here expects $JAIL, $BIND_PATHS and $EXTRA_SHIMS
|
|
# from the caller.
|
|
# ============================================================================
|
|
|
|
readonly DEFAULT_SHIMS=(
|
|
systemctl pkill pacman curl npm loginctl openrgb ddcutil i2cdetect
|
|
modprobe reboot shutdown poweroff mount umount nft iptables crontab
|
|
amixer notify-send yay makepkg
|
|
)
|
|
|
|
build_jail() {
|
|
JAIL="$(mktemp -d)"
|
|
mkdir -p "$JAIL/bin" "$JAIL/cov" "$JAIL/home" "$JAIL/etc"
|
|
|
|
local tool
|
|
for tool in "${DEFAULT_SHIMS[@]}" ${EXTRA_SHIMS[@]+"${EXTRA_SHIMS[@]}"}; do
|
|
printf '#!/usr/bin/env bash\nprintf "%%s %%s\\n" "%s" "$*" >>"%s/calls.log"\nexit 0\n' \
|
|
"$tool" "$JAIL" >"$JAIL/bin/$tool"
|
|
chmod +x "$JAIL/bin/$tool"
|
|
done
|
|
|
|
# Fact 2: give the jail a passwd where the invoking user resolves. Inside
|
|
# the userns our uid appears as 0, so the user is mapped to 0 here.
|
|
# `sudo` cannot work inside a user namespace -- it calls setresuid, which
|
|
# fails with EINVAL against an unmapped uid, and dies before running the
|
|
# command. We are already uid 0 in here, so sudo has nothing to do: this
|
|
# pass-through drops its own flags and execs the real command, which keeps
|
|
# `sudo tee /etc/foo` writing into the jail exactly as the code intends.
|
|
# It is NOT in DEFAULT_SHIMS, because recording-and-exiting would skip the
|
|
# very writes these suites exist to assert on.
|
|
cat >"$JAIL/bin/sudo" <<'SUDO'
|
|
#!/usr/bin/env bash
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
-n|-H|-E|-S|-k) shift ;;
|
|
-u) shift 2 ;;
|
|
--) shift; break ;;
|
|
*) break ;;
|
|
esac
|
|
done
|
|
[[ $# -eq 0 ]] && exit 0
|
|
exec "$@"
|
|
SUDO
|
|
chmod +x "$JAIL/bin/sudo"
|
|
|
|
local user="${USER:-$(id -un)}"
|
|
printf 'root:x:0:0::/root:/bin/bash\n%s:x:0:0::%s:/bin/bash\n' \
|
|
"$user" "$JAIL/home" >"$JAIL/etc/passwd"
|
|
printf 'root:x:0:\n%s:x:0:\n' "$user" >"$JAIL/etc/group"
|
|
printf 'passwd: files\ngroup: files\n' >"$JAIL/etc/nsswitch.conf"
|
|
|
|
# A bound path is replaced by an EMPTY dir, so anything the subject needs
|
|
# to read from it must be seeded by the caller. /etc is seeded above.
|
|
# A bound path is replaced by an EMPTY dir, so the subject's writes land
|
|
# in the jail -- but a write to <bound>/sub/dir/file fails with ENOENT if
|
|
# `sub/dir` does not exist, and a subject that aborts on that failure
|
|
# looks exactly like one whose lines are unreachable. Mirroring the real
|
|
# directory tree (names only, never file contents) keeps every write path
|
|
# valid while still capturing the data.
|
|
local path idx=0
|
|
for path in ${BIND_PATHS[@]+"${BIND_PATHS[@]}"}; do
|
|
mkdir -p "$JAIL/mnt$idx"
|
|
# -r: an unreadable target (/root as a normal user) simply has no tree
|
|
# to mirror. That is not an error -- the caller seeds what it needs with
|
|
# --seed-dir -- but cd'ing into it would abort under `set -e`.
|
|
if [[ -d $path && -r $path && -x $path ]]; then
|
|
(cd "$path" && find . -type d -not -path '*/.*' -print0 2>/dev/null) |
|
|
(cd "$JAIL/mnt$idx" && xargs -0 -r mkdir -p 2>/dev/null) || true
|
|
fi
|
|
if [[ $path == "/etc" ]]; then
|
|
cp -a "$JAIL/etc/." "$JAIL/mnt$idx/"
|
|
fi
|
|
idx=$((idx + 1))
|
|
done
|
|
}
|
|
|
|
# Written to a file and read back as an array so each case keeps its quoting;
|
|
# splitting an unquoted "$args" would need an SC2086 suppression, and this
|
|
# repo forbids suppressions.
|
|
write_cases() {
|
|
local case_str
|
|
for case_str in "${CASES[@]}"; do
|
|
printf '%s\n' "$case_str"
|
|
done >"$JAIL/cases"
|
|
}
|
|
|
|
build_mount_script() {
|
|
local path idx=0
|
|
{
|
|
for path in ${BIND_PATHS[@]+"${BIND_PATHS[@]}"}; do
|
|
# mkdir first: a bind onto a path this host does not have (/var/www on
|
|
# a machine with no webserver) fails outright, and a bind that fails
|
|
# silently is the exact misdiagnosis this runner exists to avoid --
|
|
# the subject then writes to the REAL path or dies, and the report
|
|
# shows unreachable lines either way. Hence fatal, not a warning.
|
|
printf 'mkdir -p %q 2>/dev/null || true\n' "$path"
|
|
printf 'mount --bind %q %q || { printf "Error: bind failed: %s\\n" %q >&2; exit 1; }\n' \
|
|
"$JAIL/mnt$idx" "$path" '%s' "$path"
|
|
idx=$((idx + 1))
|
|
done
|
|
} >"$JAIL/mounts.sh"
|
|
}
|