mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix(test): isolate harness daemon runtimes
Signed-off-by: astandrik <astandrik@yandex-team.ru>
This commit is contained in:
1 parent
f9e95e34a3
commit
0eb22f0205
12 files changed
+331
-32
No files matched your search
@@ -27,8 +27,11 @@ fi
|
||||
|
||||
echo "=== Fuzz Testing ($DURATION seconds) ==="
|
||||
|
||||
FUZZ_TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$FUZZ_TMPDIR"' EXIT
|
||||
# shellcheck source=test-runtime.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
FUZZ_TMPDIR="$CBM_TEST_RUNTIME_ROOT"
|
||||
trap 'cbm_test_runtime_cleanup "$BINARY"' EXIT
|
||||
|
||||
CRASHES=0
|
||||
ITERATIONS=0
|
||||
|
||||
+10
-10
@@ -22,11 +22,14 @@ PASS=0
|
||||
TOTAL=0
|
||||
|
||||
# Temp directory for input files (avoids pipe/stdin issues with timeout)
|
||||
FUZZ_TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$FUZZ_TMPDIR"' EXIT
|
||||
# shellcheck source=test-runtime.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
FUZZ_TMPDIR="$CBM_TEST_RUNTIME_ROOT"
|
||||
trap 'cbm_test_runtime_cleanup "$BINARY"' EXIT
|
||||
FUZZ_HOME="$FUZZ_TMPDIR/home"
|
||||
FUZZ_CACHE="$FUZZ_TMPDIR/cache"
|
||||
mkdir -p "$FUZZ_HOME" "$FUZZ_CACHE"
|
||||
mkdir "$FUZZ_HOME"
|
||||
export HOME="$FUZZ_HOME"
|
||||
|
||||
# Helper: send a payload to the MCP server and check it doesn't crash.
|
||||
# Uses temp file + perl alarm for portable timeout (works on macOS + Linux).
|
||||
@@ -49,11 +52,9 @@ test_payload() {
|
||||
# Run with 10s timeout: GNU timeout → perl alarm fallback
|
||||
local ec=0
|
||||
if command -v timeout &>/dev/null; then
|
||||
HOME="$FUZZ_HOME" CBM_CACHE_DIR="$FUZZ_CACHE" \
|
||||
timeout 10 "$BINARY" < "$tmpinput" > "$tmpoutput" 2>&1 || ec=$?
|
||||
timeout 10 "$BINARY" < "$tmpinput" > "$tmpoutput" 2>&1 || ec=$?
|
||||
else
|
||||
HOME="$FUZZ_HOME" CBM_CACHE_DIR="$FUZZ_CACHE" \
|
||||
perl -e 'alarm(10); exec @ARGV' -- "$BINARY" \
|
||||
perl -e 'alarm(10); exec @ARGV' -- "$BINARY" \
|
||||
< "$tmpinput" > "$tmpoutput" 2>&1 || ec=$?
|
||||
fi
|
||||
|
||||
@@ -88,8 +89,7 @@ test_invalid_index_interactive() {
|
||||
local tmpoutput="$FUZZ_TMPDIR/output_${TOTAL}.jsonl"
|
||||
local ec=0
|
||||
|
||||
HOME="$FUZZ_HOME" CBM_CACHE_DIR="$FUZZ_CACHE" \
|
||||
python3 "$(dirname "$0")/test_mcp_interactive.py" "$BINARY" \
|
||||
python3 "$(dirname "$0")/test_mcp_interactive.py" "$BINARY" \
|
||||
--scenario invalid-index --repo-path /nonexistent/path/abc123 \
|
||||
--response-timeout 45 --exit-timeout 15 > "$tmpoutput" 2>&1 || ec=$?
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Layer 4: Install output audit — verifies install --dry-run writes only to expected paths.
|
||||
# Layer 4: Install output audit — runs a sandboxed real install and audits its writes.
|
||||
#
|
||||
# Checks:
|
||||
# 1. All output file paths are in the expected set
|
||||
@@ -19,8 +19,11 @@ fi
|
||||
|
||||
echo "=== Layer 4: Install Output Audit ==="
|
||||
|
||||
TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
# shellcheck source=test-runtime.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
TMPDIR="$CBM_TEST_RUNTIME_ROOT"
|
||||
trap 'cbm_test_runtime_cleanup "$BINARY"' EXIT
|
||||
|
||||
# Set HOME to tmpdir so install writes there instead of real home
|
||||
export HOME="$TMPDIR/home"
|
||||
|
||||
@@ -30,8 +30,11 @@ if ! command -v strace &>/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
# shellcheck source=test-runtime.sh
|
||||
source "$(dirname "${BASH_SOURCE[0]}")/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
TMPDIR="$CBM_TEST_RUNTIME_ROOT"
|
||||
trap 'cbm_test_runtime_cleanup "$BINARY"' EXIT
|
||||
|
||||
# Create a minimal test project
|
||||
mkdir -p "$TMPDIR/project/src"
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Sourced by test harnesses. Host paths stay separate from paths exported to a
|
||||
# native Windows product binary.
|
||||
CBM_TEST_RUNTIME_ROOT=""
|
||||
CBM_TEST_RUNTIME_DIR_HOST=""
|
||||
CBM_TEST_CACHE_DIR_HOST=""
|
||||
_CBM_TEST_RUNTIME_CREATED_ROOT=""
|
||||
_CBM_TEST_RUNTIME_PRODUCT_RUNTIME=""
|
||||
_CBM_TEST_RUNTIME_PRODUCT_CACHE=""
|
||||
|
||||
_cbm_test_runtime_error() {
|
||||
echo "test-runtime: $*" >&2
|
||||
}
|
||||
|
||||
_cbm_test_runtime_discard_partial() {
|
||||
local root="$1" parent="$2" name="${1##*/}"
|
||||
[[ -n "$root" && "$root" != "$name" && "${root%/*}" == "$parent" && ! -L "$root" ]] || return 0
|
||||
case "$name" in cbmrt.?*|cbmrt-?*) rm -rf -- "$root" >/dev/null 2>&1 || true ;; esac
|
||||
}
|
||||
|
||||
cbm_test_runtime_init() {
|
||||
[[ -z "$_CBM_TEST_RUNTIME_CREATED_ROOT" ]] ||
|
||||
{ _cbm_test_runtime_error "runtime already initialized"; return 1; }
|
||||
local platform windows=0 parent root="" runtime_host cache_host
|
||||
local product_runtime product_cache helper_dir helper_native root_native
|
||||
platform="$(uname -s)" ||
|
||||
{ _cbm_test_runtime_error "cannot identify the host platform"; return 1; }
|
||||
case "$platform" in
|
||||
MINGW*|MSYS*|CYGWIN*) windows=1 ;;
|
||||
Darwin) parent="/private/tmp" ;;
|
||||
*) parent="/tmp" ;;
|
||||
esac
|
||||
if (( windows )); then
|
||||
command -v cygpath >/dev/null 2>&1 ||
|
||||
{ _cbm_test_runtime_error "cygpath is required on Windows"; return 1; }
|
||||
if [[ -n "${CBM_CI_TEMP_ROOT:-}" ]]; then
|
||||
parent="$(cygpath -u "$CBM_CI_TEMP_ROOT")" ||
|
||||
{ _cbm_test_runtime_error "cannot convert CBM_CI_TEMP_ROOT"; return 1; }
|
||||
[[ -d "$parent" && ! -L "$parent" ]] ||
|
||||
{ _cbm_test_runtime_error "CBM_CI_TEMP_ROOT is not a real directory"; return 1; }
|
||||
root="$(mktemp -d "${parent%/}/cbmrt.XXXXXX")" ||
|
||||
{ _cbm_test_runtime_error "cannot create a private Windows CI root"; return 1; }
|
||||
else
|
||||
helper_dir="$(CDPATH= cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || return 1
|
||||
helper_native="$(cygpath -w "$helper_dir/ci/new-protected-temp-root.ps1")" ||
|
||||
{ _cbm_test_runtime_error "cannot convert protected-root helper"; return 1; }
|
||||
root_native="$(MSYS2_ARG_CONV_EXCL='*' powershell.exe -NoProfile \
|
||||
-ExecutionPolicy Bypass -File "$helper_native" -Prefix 'cbmrt-')" ||
|
||||
{ _cbm_test_runtime_error "protected Windows root creation failed"; return 1; }
|
||||
root_native="${root_native//$'\r'/}"
|
||||
[[ -n "$root_native" && "$root_native" != *$'\n'* ]] ||
|
||||
{ _cbm_test_runtime_error "protected-root helper returned an invalid path"; return 1; }
|
||||
root="$(cygpath -u "$root_native")" ||
|
||||
{ _cbm_test_runtime_error "cannot convert protected Windows root"; return 1; }
|
||||
parent="${root%/*}"
|
||||
fi
|
||||
else
|
||||
root="$(mktemp -d "${parent%/}/cbmrt.XXXXXX")" ||
|
||||
{ _cbm_test_runtime_error "cannot create private root under $parent"; return 1; }
|
||||
chmod 700 "$root" || {
|
||||
_cbm_test_runtime_discard_partial "$root" "$parent"
|
||||
_cbm_test_runtime_error "cannot protect runtime root $root"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
runtime_host="$root/runtime"
|
||||
cache_host="$root/cache"
|
||||
mkdir "$runtime_host" "$cache_host" || {
|
||||
_cbm_test_runtime_discard_partial "$root" "$parent"
|
||||
_cbm_test_runtime_error "cannot create runtime/cache directories"
|
||||
return 1
|
||||
}
|
||||
if (( ! windows )); then
|
||||
chmod 700 "$runtime_host" "$cache_host" || {
|
||||
_cbm_test_runtime_discard_partial "$root" "$parent"
|
||||
_cbm_test_runtime_error "cannot protect runtime/cache directories"
|
||||
return 1
|
||||
}
|
||||
product_runtime="$runtime_host"
|
||||
product_cache="$cache_host"
|
||||
else
|
||||
product_runtime="$(cygpath -m "$runtime_host")" || {
|
||||
_cbm_test_runtime_discard_partial "$root" "$parent"
|
||||
_cbm_test_runtime_error "cannot convert the runtime directory"
|
||||
return 1
|
||||
}
|
||||
product_cache="$(cygpath -m "$cache_host")" || {
|
||||
_cbm_test_runtime_discard_partial "$root" "$parent"
|
||||
_cbm_test_runtime_error "cannot convert the cache directory"
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
CBM_TEST_RUNTIME_ROOT="$root"
|
||||
CBM_TEST_RUNTIME_DIR_HOST="$runtime_host"
|
||||
CBM_TEST_CACHE_DIR_HOST="$cache_host"
|
||||
_CBM_TEST_RUNTIME_CREATED_ROOT="$root"
|
||||
_CBM_TEST_RUNTIME_PRODUCT_RUNTIME="$product_runtime"
|
||||
_CBM_TEST_RUNTIME_PRODUCT_CACHE="$product_cache"
|
||||
export CBM_RUNTIME_DIR="$product_runtime" CBM_CACHE_DIR="$product_cache"
|
||||
}
|
||||
|
||||
_cbm_test_runtime_daemon() {
|
||||
CBM_RUNTIME_DIR="$_CBM_TEST_RUNTIME_PRODUCT_RUNTIME" \
|
||||
CBM_CACHE_DIR="$_CBM_TEST_RUNTIME_PRODUCT_CACHE" "$1" daemon "$2"
|
||||
}
|
||||
|
||||
cbm_test_runtime_cleanup() {
|
||||
local binary="${1:-}" root="$_CBM_TEST_RUNTIME_CREATED_ROOT"
|
||||
local name="${_CBM_TEST_RUNTIME_CREATED_ROOT##*/}" runtime_entry="" active=0
|
||||
[[ -n "$root" ]] || return 0
|
||||
case "$name" in
|
||||
cbmrt.?*|cbmrt-?*) ;;
|
||||
*) _cbm_test_runtime_error "refusing cleanup for unexpected basename: $name"; return 0 ;;
|
||||
esac
|
||||
if [[ "$root" != "$CBM_TEST_RUNTIME_ROOT" || -L "$root" ]]; then
|
||||
_cbm_test_runtime_error "refusing cleanup for an unexpected runtime root: $root"
|
||||
return 0
|
||||
fi
|
||||
if [[ ! -e "$root" ]]; then
|
||||
_CBM_TEST_RUNTIME_CREATED_ROOT=""
|
||||
return 0
|
||||
fi
|
||||
if [[ ! -d "$root" || "$CBM_TEST_RUNTIME_DIR_HOST" != "$root/runtime" ||
|
||||
"$CBM_TEST_CACHE_DIR_HOST" != "$root/cache" ||
|
||||
-L "$CBM_TEST_RUNTIME_DIR_HOST" || -L "$CBM_TEST_CACHE_DIR_HOST" ]]; then
|
||||
_cbm_test_runtime_error "refusing cleanup after runtime path replacement: $root"
|
||||
return 0
|
||||
fi
|
||||
if [[ -d "$CBM_TEST_RUNTIME_DIR_HOST" ]] &&
|
||||
! runtime_entry="$(find "$CBM_TEST_RUNTIME_DIR_HOST" -mindepth 1 -print -quit 2>/dev/null)"; then
|
||||
_cbm_test_runtime_error "cannot inspect runtime state; leaving $root"
|
||||
return 0
|
||||
fi
|
||||
if [[ -n "$runtime_entry" ]]; then
|
||||
[[ -x "$binary" ]] || {
|
||||
_cbm_test_runtime_error "cannot check the private daemon; leaving $root"
|
||||
return 0
|
||||
}
|
||||
if _cbm_test_runtime_daemon "$binary" status >/dev/null 2>&1; then
|
||||
active=1
|
||||
_cbm_test_runtime_daemon "$binary" stop >/dev/null 2>&1 || true
|
||||
for _attempt in {1..50}; do
|
||||
if ! _cbm_test_runtime_daemon "$binary" status >/dev/null 2>&1; then
|
||||
active=0
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if (( active )); then
|
||||
_cbm_test_runtime_error "private daemon is still active; leaving $root"
|
||||
return 0
|
||||
fi
|
||||
if rm -rf -- "$root"; then
|
||||
_CBM_TEST_RUNTIME_CREATED_ROOT=""
|
||||
else
|
||||
_cbm_test_runtime_error "cleanup failed; leaving $root"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
+4
-1
@@ -14,7 +14,7 @@ Usage: scripts/test.sh [--suites LIST] [--arch ARCH] [VAR=VAL ...]
|
||||
|
||||
The canonical test entry: identical in local CI, PR CI, dry run and release.
|
||||
DEFAULT (no --suites) is exactly what CI runs: static contract checks
|
||||
(Step 0a-0s), a CLEAN sanitizer build, every suite via the parallel harness,
|
||||
(Step 0a-0t), a CLEAN sanitizer build, every suite via the parallel harness,
|
||||
then the prod-binary regression guards (Steps 4-6).
|
||||
|
||||
Modes:
|
||||
@@ -257,6 +257,9 @@ bash "$ROOT/tests/test_vt_candidate_selection_contract.sh"
|
||||
echo "=== Step 0s: release gate-chain ordering contract ==="
|
||||
bash "$ROOT/tests/test_release_gate_chain_contract.sh"
|
||||
|
||||
echo "=== Step 0t: test runtime isolation contract (#1691) ==="
|
||||
bash "$ROOT/tests/test_runtime_isolation_contract.sh"
|
||||
|
||||
# Verify compiler supports target arch
|
||||
verify_compiler "$CC"
|
||||
|
||||
|
||||
@@ -44,10 +44,13 @@ if ! LC_ALL=C grep -a -q -F 'CBM_TEST_HOOK_CLIENT_BUILD' "${BINARY}"; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
# shellcheck source=../scripts/test-runtime.sh
|
||||
source "${ROOT}/scripts/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
tmpdir="${CBM_TEST_RUNTIME_ROOT}"
|
||||
cleanup() {
|
||||
CBM_CACHE_DIR="${tmpdir}/cache" "${BINARY}" daemon stop >/dev/null 2>&1 || true
|
||||
rm -rf "${tmpdir}"
|
||||
cbm_test_runtime_cleanup "${BINARY}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
|
||||
@@ -25,7 +25,10 @@ if [[ ! -x "${BINARY}" ]]; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
# shellcheck source=../scripts/test-runtime.sh
|
||||
source "${ROOT}/scripts/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
tmpdir="${CBM_TEST_RUNTIME_ROOT}"
|
||||
wrapper_pid=""
|
||||
cleanup() {
|
||||
if [[ -s "${tmpdir}/child.pid" ]]; then
|
||||
@@ -34,7 +37,7 @@ cleanup() {
|
||||
[[ -n "${child_pid}" ]] && kill "${child_pid}" 2>/dev/null || true
|
||||
fi
|
||||
[[ -n "${wrapper_pid}" ]] && kill "${wrapper_pid}" 2>/dev/null || true
|
||||
rm -rf "${tmpdir}"
|
||||
cbm_test_runtime_cleanup "${BINARY}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
WORKDIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$WORKDIR"' EXIT
|
||||
fail() {
|
||||
echo "FAIL: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
normalize_path() {
|
||||
local path="${1%$'\r'}"
|
||||
if command -v cygpath >/dev/null 2>&1; then
|
||||
cygpath -u "$path" 2>/dev/null && return 0
|
||||
fi
|
||||
printf '%s\n' "${path//\\//}"
|
||||
}
|
||||
INSTALL_FIXTURE="$WORKDIR/install-fixture"
|
||||
cat > "$INSTALL_FIXTURE" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
[[ "$1 $2" == "daemon status" ]] && exit 1
|
||||
if [[ "$1 $2" == "install -y" ]]; then
|
||||
printf '%s\t%s\t%s\n' "$HOME" "$CBM_CACHE_DIR" "$CBM_RUNTIME_DIR" > "$CBM_TEST_INSTALL_ENV_PROBE"
|
||||
fi
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$INSTALL_FIXTURE"
|
||||
CONTROL="$INSTALL_FIXTURE"
|
||||
CALLER_ROOT="$WORKDIR/caller-a"
|
||||
mkdir -p "$CALLER_ROOT/runtime" "$CALLER_ROOT/cache"
|
||||
touch "$CALLER_ROOT/sentinel"
|
||||
(
|
||||
export CBM_RUNTIME_DIR="$CALLER_ROOT/runtime"
|
||||
export CBM_CACHE_DIR="$CALLER_ROOT/cache"
|
||||
source "$ROOT/scripts/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
[[ "$CBM_RUNTIME_DIR" != "$CALLER_ROOT/runtime" ]] || fail "inherited runtime was reused"
|
||||
[[ "$CBM_CACHE_DIR" != "$CALLER_ROOT/cache" ]] || fail "inherited cache was reused"
|
||||
private_root="$CBM_TEST_RUNTIME_ROOT"
|
||||
[[ -d "$private_root/runtime" && -d "$private_root/cache" ]] || fail "private directories missing"
|
||||
cbm_test_runtime_cleanup "$CONTROL"
|
||||
[[ ! -e "$private_root" ]] || fail "normal cleanup left its private root"
|
||||
)
|
||||
[[ -f "$CALLER_ROOT/sentinel" ]] || fail "cleanup touched the caller root"
|
||||
for slot in 1 2; do
|
||||
(
|
||||
source "$ROOT/scripts/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
printf '%s\n' "$CBM_TEST_RUNTIME_ROOT" > "$WORKDIR/root-$slot"
|
||||
cbm_test_runtime_cleanup "$CONTROL"
|
||||
) &
|
||||
done
|
||||
wait
|
||||
[[ "$(<"$WORKDIR/root-1")" != "$(<"$WORKDIR/root-2")" ]] || fail "parallel roots collided"
|
||||
FAIL_FIXTURE="$WORKDIR/failure-fixture"
|
||||
cat > "$FAIL_FIXTURE" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
touch "$CBM_TEST_FAILURE_MARKER"
|
||||
EOF
|
||||
chmod +x "$FAIL_FIXTURE"
|
||||
mkdir "$WORKDIR/windows-ci-root"
|
||||
set +e
|
||||
(
|
||||
set -e
|
||||
source "$ROOT/scripts/test-runtime.sh"
|
||||
case "$(uname -s)" in
|
||||
MINGW*|MSYS*|CYGWIN*) export CBM_CI_TEMP_ROOT="$(cygpath -m "$WORKDIR/windows-ci-root")" ;;
|
||||
esac
|
||||
mktemp() { return 1; }
|
||||
cbm_test_runtime_init
|
||||
CBM_TEST_FAILURE_MARKER="$WORKDIR/failure.marker" "$FAIL_FIXTURE"
|
||||
) > "$WORKDIR/failure.out" 2>&1
|
||||
failure_rc=$?
|
||||
set -e
|
||||
[[ $failure_rc -ne 0 ]] || fail "simulated creation failure did not stop the harness"
|
||||
[[ ! -e "$WORKDIR/failure.marker" ]] || fail "fixture ran after runtime creation failed"
|
||||
mkdir "$WORKDIR/caller-home" "$WORKDIR/caller-cache" "$WORKDIR/caller-runtime"
|
||||
HOME="$WORKDIR/caller-home" \
|
||||
CBM_CACHE_DIR="$WORKDIR/caller-cache" \
|
||||
CBM_RUNTIME_DIR="$WORKDIR/caller-runtime" \
|
||||
CBM_TEST_INSTALL_ENV_PROBE="$WORKDIR/install.env" \
|
||||
"$ROOT/scripts/security-install.sh" "$INSTALL_FIXTURE" > "$WORKDIR/install.out" 2>&1
|
||||
IFS=$'\t' read -r install_home install_cache install_runtime < "$WORKDIR/install.env"
|
||||
install_home="$(normalize_path "$install_home")"
|
||||
install_cache="$(normalize_path "$install_cache")"
|
||||
install_runtime="$(normalize_path "$install_runtime")"
|
||||
[[ "$install_home" != "$(normalize_path "$WORKDIR/caller-home")" ]] || fail "install reused caller HOME"
|
||||
[[ "$install_cache" != "$(normalize_path "$WORKDIR/caller-cache")" ]] || fail "install reused caller cache"
|
||||
[[ "$install_runtime" != "$(normalize_path "$WORKDIR/caller-runtime")" ]] || fail "install reused caller runtime"
|
||||
install_root="${install_home%/*}"
|
||||
[[ "$install_home" == "$install_root/home" && "$install_cache" == "$install_root/cache" &&
|
||||
"$install_runtime" == "$install_root/runtime" ]] || fail "install env did not share one private root"
|
||||
ENTRY_POINTS=(
|
||||
scripts/security-install.sh scripts/security-fuzz.sh scripts/security-fuzz-random.sh
|
||||
scripts/security-network.sh tests/test_parent_watchdog.sh tests/test_worker_watchdog.sh
|
||||
tests/test_worker_error_response.sh tests/test_hook_conflict_notice.sh
|
||||
)
|
||||
for entry in "${ENTRY_POINTS[@]}"; do
|
||||
grep -q 'test-runtime.sh' "$ROOT/$entry" || fail "$entry does not source the helper"
|
||||
grep -q 'cbm_test_runtime_init' "$ROOT/$entry" || fail "$entry does not initialize isolation"
|
||||
grep -q 'cbm_test_runtime_cleanup' "$ROOT/$entry" || fail "$entry does not clean isolation"
|
||||
done
|
||||
echo "PASS: test harness runtimes are private, unique, fail-closed, and wired"
|
||||
@@ -44,7 +44,7 @@ fi
|
||||
ENV_PROBE="$WORKDIR/environment-probe-mcp"
|
||||
cat > "$ENV_PROBE" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
printf '%s\t%s\n' "${HOME-}" "${CBM_CACHE_DIR-}" >> "$CBM_FUZZ_ENV_PROBE"
|
||||
printf '%s\t%s\t%s\n' "${HOME-}" "${CBM_CACHE_DIR-}" "${CBM_RUNTIME_DIR-}" >> "$CBM_FUZZ_ENV_PROBE"
|
||||
|
||||
# Echo a JSON-RPC result for every request with a numeric id. This keeps the
|
||||
# fixture compatible with both the current fixed ids and a future per-case
|
||||
@@ -64,11 +64,13 @@ chmod +x "$ENV_PROBE"
|
||||
|
||||
CALLER_HOME="$WORKDIR/caller-home"
|
||||
CALLER_CACHE="$WORKDIR/caller-cache"
|
||||
CALLER_RUNTIME="$WORKDIR/caller-runtime"
|
||||
ENV_LOG="$WORKDIR/environment.log"
|
||||
mkdir -p "$CALLER_HOME" "$CALLER_CACHE"
|
||||
mkdir -p "$CALLER_HOME" "$CALLER_CACHE" "$CALLER_RUNTIME"
|
||||
|
||||
if ! HOME="$CALLER_HOME" \
|
||||
CBM_CACHE_DIR="$CALLER_CACHE" \
|
||||
CBM_RUNTIME_DIR="$CALLER_RUNTIME" \
|
||||
CBM_FUZZ_ENV_PROBE="$ENV_LOG" \
|
||||
"$ROOT/scripts/security-fuzz.sh" "$ENV_PROBE" \
|
||||
> "$WORKDIR/environment.out" 2>&1; then
|
||||
@@ -92,10 +94,12 @@ normalize_path() {
|
||||
|
||||
CALLER_HOME_NORMALIZED=$(normalize_path "$CALLER_HOME")
|
||||
CALLER_CACHE_NORMALIZED=$(normalize_path "$CALLER_CACHE")
|
||||
CALLER_RUNTIME_NORMALIZED=$(normalize_path "$CALLER_RUNTIME")
|
||||
|
||||
while IFS=$'\t' read -r child_home_raw child_cache_raw; do
|
||||
while IFS=$'\t' read -r child_home_raw child_cache_raw child_runtime_raw; do
|
||||
child_home=$(normalize_path "$child_home_raw")
|
||||
child_cache=$(normalize_path "$child_cache_raw")
|
||||
child_runtime=$(normalize_path "$child_runtime_raw")
|
||||
if [[ -z "$child_home" || "$child_home" == "$CALLER_HOME_NORMALIZED" ]]; then
|
||||
echo "FAIL: security-fuzz exposed the caller HOME to a fuzz target"
|
||||
exit 1
|
||||
@@ -104,14 +108,21 @@ while IFS=$'\t' read -r child_home_raw child_cache_raw; do
|
||||
echo "FAIL: security-fuzz exposed the caller CBM_CACHE_DIR to a fuzz target"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "$child_runtime" || "$child_runtime" == "$CALLER_RUNTIME_NORMALIZED" ]]; then
|
||||
echo "FAIL: security-fuzz exposed the caller CBM_RUNTIME_DIR to a fuzz target"
|
||||
exit 1
|
||||
fi
|
||||
child_home_parent=${child_home%/*}
|
||||
child_cache_parent=${child_cache%/*}
|
||||
child_runtime_parent=${child_runtime%/*}
|
||||
if [[ "$child_home_parent" != "$child_cache_parent" ||
|
||||
"$child_home_parent" != "$child_runtime_parent" ||
|
||||
"${child_home##*/}" != "home" ||
|
||||
"${child_cache##*/}" != "cache" ]]; then
|
||||
echo "FAIL: fuzz HOME/cache were not isolated beneath one harness temp directory"
|
||||
"${child_cache##*/}" != "cache" ||
|
||||
"${child_runtime##*/}" != "runtime" ]]; then
|
||||
echo "FAIL: fuzz HOME/cache/runtime were not isolated beneath one harness temp directory"
|
||||
exit 1
|
||||
fi
|
||||
done < "$ENV_LOG"
|
||||
|
||||
echo "PASS: security fuzz harness requires payload progress and isolates HOME/cache"
|
||||
echo "PASS: security fuzz harness requires payload progress and isolates HOME/cache/runtime"
|
||||
@@ -35,11 +35,14 @@ if [[ ! "${BUILD_FINGERPRINT}" =~ ^[0-9a-f]{64}$ ]]; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
# shellcheck source=../scripts/test-runtime.sh
|
||||
source "${ROOT}/scripts/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
tmpdir="${CBM_TEST_RUNTIME_ROOT}"
|
||||
cleanup() {
|
||||
CBM_CACHE_DIR="${tmpdir}/cache-supervisor" \
|
||||
"${BINARY}" daemon stop >/dev/null 2>&1 || true
|
||||
rm -rf "${tmpdir}"
|
||||
cbm_test_runtime_cleanup "${BINARY}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
|
||||
@@ -65,7 +65,10 @@ if [[ ! "${BUILD_FINGERPRINT}" =~ ^[0-9a-f]{64}$ ]]; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
# shellcheck source=../scripts/test-runtime.sh
|
||||
source "${ROOT}/scripts/test-runtime.sh"
|
||||
cbm_test_runtime_init
|
||||
tmpdir="${CBM_TEST_RUNTIME_ROOT}"
|
||||
wrapper_pid=""
|
||||
cleanup() {
|
||||
if [[ -s "${tmpdir}/child.pid" ]]; then
|
||||
@@ -79,7 +82,7 @@ cleanup() {
|
||||
[[ -n "${descendant_pid}" ]] && kill -9 "${descendant_pid}" 2>/dev/null || true
|
||||
fi
|
||||
[[ -n "${wrapper_pid}" ]] && kill -9 "${wrapper_pid}" 2>/dev/null || true
|
||||
rm -rf "${tmpdir}"
|
||||
cbm_test_runtime_cleanup "${BINARY}"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
|
||||
Reference in new issue
Block a user