feat: add isolated Linux shadow backend

This commit is contained in:
冰朔 2026-08-15 17:34:30 +08:00
commit f5217fef0f
6 changed files with 283 additions and 2 deletions

View file

@ -78,6 +78,19 @@ at 100% of declared source lines and functions. No production Linux
subcontrol backend, independent Guanghu boot supervisor, JD boot change, or
physical cutover is implied by that source result.
`scripts/linux-subcontrol-docker-backend.sh` is the first executable shadow
backend for the Linux-hosted transition. It binds the exact JD instance,
backend id, immutable Ubuntu image digest, and preserved GRUB rescue slot. A
wake starts a networkless, read-only, capability-free container with explicit
CPU, memory, and PID limits. Only the registered runtime-identity readback is
accepted; reclaim removes the container and verifies `DORMANT`. Environment
path overrides are rejected outside the isolated test harness.
This backend can prove the bounded Linux lifecycle while Ubuntu is still the
host. It cannot prove Guanghu-first boot control or the final topology. Those
remain `0` until the same lifecycle is owned by an independently booted
Guanghu supervisor and has a current JD server receipt.
## Language-primary boot target
`guanghu-language-primary.target` makes the accepted cognitive-control model

View file

@ -0,0 +1,166 @@
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
die() {
echo "GUANGHU_LINUX_SUBCONTROL_FAIL_0: $*" >&2
exit 1
}
test_mode=${GH_SUBCONTROL_TEST_MODE:-0}
if [[ "${test_mode}" == 1 ]]; then
config_path=${GH_SUBCONTROL_CONFIG:?test config is required}
docker_bin=${GH_SUBCONTROL_DOCKER:?test docker is required}
dmi_path=${GH_SUBCONTROL_DMI_PATH:?test DMI path is required}
grub_cfg=${GH_SUBCONTROL_GRUB_CFG:?test GRUB path is required}
state_root=${GH_SUBCONTROL_STATE_ROOT:?test state root is required}
receipt_root=${GH_SUBCONTROL_RECEIPT_ROOT:?test receipt root is required}
else
[[ "${EUID}" == 0 ]] || die "root execution is required"
for override in \
GH_SUBCONTROL_CONFIG GH_SUBCONTROL_DOCKER GH_SUBCONTROL_DMI_PATH \
GH_SUBCONTROL_GRUB_CFG GH_SUBCONTROL_STATE_ROOT GH_SUBCONTROL_RECEIPT_ROOT; do
[[ -z "${!override:-}" ]] || die "production path override is forbidden: ${override}"
done
config_path=/etc/guanghu/linux-subcontrol.conf
docker_bin=/usr/bin/docker
dmi_path=/sys/class/dmi/id/product_uuid
grub_cfg=/boot/grub/grub.cfg
state_root=/run/guanghu/linux-subcontrol
receipt_root=/guanghu/receipts/linux-subcontrol
[[ -f "${config_path}" && ! -L "${config_path}" ]] || die "root-owned backend config is missing"
[[ "$(stat -c '%u:%a' "${config_path}")" =~ ^0:(600|640|644)$ ]] ||
die "backend config owner or mode is unsafe"
fi
schema=
node_id=
instance_id=
backend_id=
container_name=
image=
rescue_slot_id=
while IFS='=' read -r key value; do
[[ -n "${key}" ]] || continue
case "${key}" in
schema|node_id|instance_id|backend_id|container_name|image|rescue_slot_id)
printf -v "${key}" '%s' "${value}"
;;
*) die "unknown config field: ${key}" ;;
esac
done <"${config_path}"
[[ "${schema}" == "guanghu.linux-subcontrol-docker-backend/v1" ]] || die "config schema mismatch"
[[ "${node_id}" == "JD-FD-PRIMARY" ]] || die "target node mismatch"
[[ "${instance_id}" =~ ^[0-9a-f-]{36}$ ]] || die "instance id is invalid"
[[ "${backend_id}" =~ ^[a-z0-9-]+$ ]] || die "backend id is invalid"
[[ "${container_name}" =~ ^[a-z0-9-]+$ ]] || die "container name is invalid"
[[ "${image}" =~ ^ubuntu@sha256:[0-9a-f]{64}$ ]] || die "image must use an immutable Ubuntu digest"
[[ "${rescue_slot_id}" =~ ^[A-Za-z0-9._-]+$ ]] || die "rescue slot id is invalid"
[[ -x "${docker_bin}" ]] || die "docker executable is unavailable"
requested_backend=${2:-}
[[ -n "${requested_backend}" && "${requested_backend}" == "${backend_id}" ]] ||
die "backend binding mismatch"
verify_machine() {
local observed
observed=$(tr '[:upper:]' '[:lower:]' <"${dmi_path}")
[[ "${observed}" == "${instance_id}" ]] || die "machine identity mismatch"
}
verify_rescue() {
grep -Fq -- "--id '${rescue_slot_id}'" "${grub_cfg}" ||
die "independent Linux rescue slot is unavailable"
}
container_running() {
[[ "$("${docker_bin}" inspect --format '{{.State.Running}}' "${container_name}" 2>/dev/null || true)" == true ]]
}
observe() {
if container_running; then
echo ready
else
echo dormant
fi
}
action=${1:-}
case "${action}" in
preflight)
verify_machine
verify_rescue
"${docker_bin}" image inspect "${image}" >/dev/null
echo "GUANGHU_LINUX_SUBCONTROL_PREFLIGHT_OK"
;;
observe)
observe
;;
wake)
verify_machine
verify_rescue
[[ "$(observe)" == dormant ]] || die "backend is not dormant before wake"
"${docker_bin}" image inspect "${image}" >/dev/null
mkdir -p "${state_root}" "${receipt_root}"
"${docker_bin}" run \
--detach \
--pull never \
--name "${container_name}" \
--hostname jd-linux-subcontrol \
--label guanghu.owner=GUANGHU_OS \
--label "guanghu.node=${node_id}" \
--label "guanghu.backend=${backend_id}" \
--network none \
--read-only \
--tmpfs /run:rw,nosuid,nodev,noexec,size=16m \
--tmpfs /tmp:rw,nosuid,nodev,noexec,size=16m \
--cap-drop ALL \
--security-opt no-new-privileges \
--pids-limit 64 \
--memory 256m \
--cpus 0.50 \
"${image}" \
/bin/sh -ceu 'trap "exit 0" TERM INT; while :; do sleep 3600 & wait $!; done' \
>/dev/null
container_running || die "backend failed readiness readback"
echo "GUANGHU_LINUX_SUBCONTROL_READY"
;;
execute|verify)
capability=${3:-}
request_id=${4:-}
[[ "${capability}" == runtime-identity-readback ]] || die "capability is not allowlisted"
[[ "${request_id}" =~ ^[A-Za-z0-9._-]+$ ]] || die "request id is invalid"
container_running || die "backend is not ready"
mkdir -p "${state_root}" "${receipt_root}"
target_file="${state_root}/${request_id}.target"
if [[ "${action}" == execute ]]; then
temporary="${target_file}.tmp"
"${docker_bin}" exec "${container_name}" /bin/sh -ceu \
'. /etc/os-release; printf "ID=%s\nVERSION_ID=%s\n" "$ID" "$VERSION_ID"' \
>"${temporary}"
chmod 600 "${temporary}"
mv "${temporary}" "${target_file}"
echo "GUANGHU_LINUX_SUBCONTROL_EXECUTED"
else
[[ -f "${target_file}" ]] || die "target readback is missing"
expected=$'ID=ubuntu\nVERSION_ID=22.04'
stored=$(cat "${target_file}")
live=$("${docker_bin}" exec "${container_name}" /bin/sh -ceu \
'. /etc/os-release; printf "ID=%s\nVERSION_ID=%s\n" "$ID" "$VERSION_ID"')
[[ "${stored}" == "${expected}" && "${live}" == "${expected}" ]] ||
die "target readback mismatch"
echo "GUANGHU_LINUX_SUBCONTROL_TARGET_VERIFIED"
fi
;;
reclaim)
if container_running; then
"${docker_bin}" rm --force "${container_name}" >/dev/null
fi
[[ "$(observe)" == dormant ]] || die "backend reclaim failed"
echo "GUANGHU_LINUX_SUBCONTROL_DORMANT"
;;
*)
die "usage: $0 <preflight|observe|wake|execute|verify|reclaim> <backend-id> [capability] [request-id]"
;;
esac

View file

@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -Eeuo pipefail
source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
adapter="${source_root}/scripts/linux-subcontrol-docker-backend.sh"
fixture=$(mktemp -d)
trap 'rm -rf "${fixture}"' EXIT
mkdir -p "${fixture}/bin" "${fixture}/state" "${fixture}/receipts"
printf '%s\n' 'f3d4b730-7f02-452f-975b-7091a4800431' >"${fixture}/dmi"
printf '%s\n' "menuentry 'Ubuntu' --id 'gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6' {" >"${fixture}/grub.cfg"
cat >"${fixture}/backend.conf" <<'EOF'
schema=guanghu.linux-subcontrol-docker-backend/v1
node_id=JD-FD-PRIMARY
instance_id=f3d4b730-7f02-452f-975b-7091a4800431
backend_id=jd-linux-on-demand
container_name=guanghu-linux-subcontrol-jd
image=ubuntu@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
rescue_slot_id=gnulinux-simple-9e4550a0-452b-4f28-b5a5-d5364aa450f6
EOF
cat >"${fixture}/bin/docker" <<'EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
printf '%s\n' "$*" >>"${FAKE_DOCKER_LOG}"
case "${1:-}" in
image)
[[ "${2:-}" == inspect ]]
;;
inspect)
[[ -f "${FAKE_DOCKER_STATE}" ]] || exit 1
printf '%s\n' true
;;
run)
touch "${FAKE_DOCKER_STATE}"
printf '%s\n' fixture-container-id
;;
exec)
[[ -f "${FAKE_DOCKER_STATE}" ]]
printf '%s\n' 'ID=ubuntu' 'VERSION_ID=22.04'
;;
rm)
rm -f "${FAKE_DOCKER_STATE}"
;;
*)
exit 64
;;
esac
EOF
chmod +x "${fixture}/bin/docker"
export GH_SUBCONTROL_TEST_MODE=1
export GH_SUBCONTROL_CONFIG="${fixture}/backend.conf"
export GH_SUBCONTROL_DOCKER="${fixture}/bin/docker"
export GH_SUBCONTROL_DMI_PATH="${fixture}/dmi"
export GH_SUBCONTROL_GRUB_CFG="${fixture}/grub.cfg"
export GH_SUBCONTROL_STATE_ROOT="${fixture}/state"
export GH_SUBCONTROL_RECEIPT_ROOT="${fixture}/receipts"
export FAKE_DOCKER_LOG="${fixture}/docker.log"
export FAKE_DOCKER_STATE="${fixture}/container.running"
[[ "$("${adapter}" observe jd-linux-on-demand)" == dormant ]]
"${adapter}" preflight jd-linux-on-demand
"${adapter}" wake jd-linux-on-demand
[[ "$("${adapter}" observe jd-linux-on-demand)" == ready ]]
"${adapter}" execute jd-linux-on-demand runtime-identity-readback REQ-001
"${adapter}" verify jd-linux-on-demand runtime-identity-readback REQ-001
"${adapter}" reclaim jd-linux-on-demand
[[ "$("${adapter}" observe jd-linux-on-demand)" == dormant ]]
grep -Fq -- '--network none' "${fixture}/docker.log"
grep -Fq -- '--read-only' "${fixture}/docker.log"
grep -Fq -- '--cap-drop ALL' "${fixture}/docker.log"
grep -Fq -- '--security-opt no-new-privileges' "${fixture}/docker.log"
grep -Fq -- '--pids-limit 64' "${fixture}/docker.log"
grep -Fq -- 'ubuntu@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' "${fixture}/docker.log"
if "${adapter}" execute jd-linux-on-demand arbitrary-shell REQ-002; then
echo "unregistered capability was accepted" >&2
exit 1
fi
printf '%s\n' 'wrong-instance' >"${fixture}/dmi"
if "${adapter}" wake jd-linux-on-demand; then
echo "wrong machine identity was accepted" >&2
exit 1
fi
printf '%s\n' 'f3d4b730-7f02-452f-975b-7091a4800431' >"${fixture}/dmi"
: >"${fixture}/grub.cfg"
if "${adapter}" wake jd-linux-on-demand; then
echo "missing rescue slot was accepted" >&2
exit 1
fi
echo "GUANGHU_LINUX_SUBCONTROL_DOCKER_BACKEND_OK"

View file

@ -88,6 +88,8 @@ run_gate world_and_protocol_validation \
run_gate shell_syntax bash -c \
'for script in "$1"/scripts/*.sh "$1"/world-seed/scripts/*.sh; do bash -n "$script"; done' \
_ "${source_root}"
run_gate linux_subcontrol_docker_backend \
"${source_root}/scripts/test-linux-subcontrol-docker-backend.sh"
run_gate auditable_line_coverage_100_percent \
bash -c '
cargo llvm-cov clean --workspace --manifest-path "$1/Cargo.toml"

View file

@ -1,7 +1,7 @@
{
"schema": "guanghu.os-control-architecture/v1",
"record_id": "HLP-GUANGHU-OS-CONTROL-001",
"version": "2026-08-15.1",
"version": "2026-08-15.2",
"state": "CURRENT_CANONICAL",
"final_topology": "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE",
"control_ownership": {
@ -46,7 +46,9 @@
"typed_policy_authorization_and_rollback_binding": 100,
"target_readback_and_mandatory_reclaim_state_machine": 100,
"declared_supervisor_core_line_and_function_coverage": 100,
"docker_shadow_backend_source_and_isolation_contract": 100,
"real_isolated_linux_backend": 0,
"jd_shadow_backend_physical_cycle": 0,
"independent_guanghu_first_boot_supervisor": 0,
"jd_physical_deployment": 0
},

View file

@ -32,11 +32,13 @@ test("current JD state stays transitional and cannot impersonate final master co
});
test("source lifecycle progress does not impersonate backend, boot, or JD deployment", () => {
assert.equal(contract.version, "2026-08-15.1");
assert.equal(contract.version, "2026-08-15.2");
assert.equal(contract.implementation.guanghu_supervisor_lifecycle_contract_source, 100);
assert.equal(contract.implementation.target_readback_and_mandatory_reclaim_state_machine, 100);
assert.equal(contract.implementation.declared_supervisor_core_line_and_function_coverage, 100);
assert.equal(contract.implementation.docker_shadow_backend_source_and_isolation_contract, 100);
assert.equal(contract.implementation.real_isolated_linux_backend, 0);
assert.equal(contract.implementation.jd_shadow_backend_physical_cycle, 0);
assert.equal(contract.implementation.independent_guanghu_first_boot_supervisor, 0);
assert.equal(contract.implementation.jd_physical_deployment, 0);
});