fix(native): gate JD final candidate replacement

This commit is contained in:
冰朔 2026-08-07 00:33:19 +08:00
commit 42d5b0c622

View file

@ -0,0 +1,97 @@
#!/usr/bin/env bash
set -euo pipefail
[[ $# -eq 6 ]] || {
echo "usage: replace-jd-native-final-resident-candidate.sh <world-root> <candidate-image> <recovery-root> <expected-old-sha256> <expected-new-sha256> <accepted-source-commit>" >&2
exit 64
}
[[ ${EUID} -eq 0 ]] || exit 77
world_root=$(readlink -f "$1")
candidate=$(readlink -f "$2")
recovery_root=$(readlink -m "$3")
expected_old_sha=$4
expected_new_sha=$5
accepted_source_commit=$6
grep -q '^node_id: JD-FD-PRIMARY$' "${world_root}/CURRENT.hldp"
/guanghu/bin/ghctl authorize "${world_root}" \
write_bootloader_and_system_partitions >/dev/null
[[ ${expected_old_sha} =~ ^[0-9a-f]{64}$ ]]
[[ ${expected_new_sha} =~ ^[0-9a-f]{64}$ ]]
[[ ${accepted_source_commit} =~ ^[0-9a-f]{40}$ ]]
[[ $(stat -c %s "${candidate}") -eq 14848 ]]
[[ $(sha256sum "${candidate}" | awk '{print $1}') == "${expected_new_sha}" ]]
[[ ! -e ${recovery_root} ]]
partition_dump=$(sfdisk -d /dev/vda)
grep -q '^label: dos$' <<<"${partition_dump}"
grep -q '^label-id: 0xf4bb72a5$' <<<"${partition_dump}"
grep -Eq '^/dev/vda1 : start= *2048, size= *209713119, type=83$' \
<<<"${partition_dump}"
observed_old_sha=$(dd if=/dev/vda bs=512 skip=105 count=29 status=none |
sha256sum | awk '{print $1}')
[[ ${observed_old_sha} == "${expected_old_sha}" ]]
dd if=/dev/vda bs=512 skip=135 count=1 status=none |
grep -aq '^GHOS_HLDP_WORLD_STORE_V1'
dd if=/dev/vda bs=512 skip=136 count=1 status=none |
grep -aq '^GHOS_CODE_CHANNEL_STORE_V1'
dd if=/dev/vda bs=512 skip=138 count=1 status=none |
grep -aq '^GHOS_BRANCH_MAIN_V1'
dd if=/dev/vda bs=512 skip=141 count=1 status=none |
grep -aq '^GHOS_GHCIP_INDEX_V1'
dd if=/dev/vda bs=512 skip=142 count=1 status=none |
grep -aq '^GHOS_GHCIP_ROOT_V1'
grep -q '^GRUB_DEFAULT=guanghu-jd-native-once$' /etc/default/grub
grep -q 'set default="guanghu-jd-native-once"' /boot/grub/grub.cfg
mkdir -m 0700 "${recovery_root}"
printf '%s\n' "${partition_dump}" >"${recovery_root}/sfdisk-before.txt"
disk_sectors=$(blockdev --getsz /dev/vda)
dd if=/dev/vda of="${recovery_root}/first-2MiB.before.bin" \
bs=1M count=2 status=none
dd if=/dev/vda of="${recovery_root}/last-2MiB.before.bin" \
bs=512 skip=$((disk_sectors - 4096)) count=4096 status=none
dd if=/dev/vda of="${recovery_root}/previous-native-candidate.img" \
bs=512 skip=105 count=29 status=none
cp /boot/grub/grub.cfg "${recovery_root}/grub.cfg.before"
cp /boot/grub/grubenv "${recovery_root}/grubenv.before"
cp /etc/default/grub "${recovery_root}/default-grub.before"
cp "${candidate}" "${recovery_root}/jd-native-final-resident.img"
dd if="${candidate}" of=/dev/vda bs=512 seek=105 count=29 \
conv=notrunc,fsync status=none
observed_new_sha=$(dd if=/dev/vda bs=512 skip=105 count=29 status=none |
sha256sum | awk '{print $1}')
[[ ${observed_new_sha} == "${expected_new_sha}" ]]
observed_at=$(date --iso-8601=seconds)
cat >"${recovery_root}/REPLACE-RECEIPT.hldp" <<EOF
schema: guanghu.jd-native-final-resident-replace/v1
receipt_id: GH-OS-JD-FD-PRIMARY-001-FINAL-RESIDENT-REPLACE
status: VERIFIED_NOT_REBOOTED
observed_at: ${observed_at}
node_id: JD-FD-PRIMARY
source:
accepted_repository_commit: ${accepted_source_commit}
candidate:
lba_start: 105
sector_count: 29
previous_sha256: ${observed_old_sha}
final_resident_sha256: ${observed_new_sha}
preserved:
proof_lba_134: true
world_and_code_store_lba_135_138: true
recovery_beacon_lba_139_140: true
gestational_index_lba_141_142: true
grub_default_native: true
rollback:
recovery_root: ${recovery_root}
first_and_last_2mib_backed_up: true
previous_candidate_backed_up: true
next_action: START_PROTECTED_RELAY_THEN_REBOOT_TO_PHYSICAL_FINAL_RESIDENCY_GATE
EOF
chmod 0400 "${recovery_root}"/*
sync
cat "${recovery_root}/REPLACE-RECEIPT.hldp"