fix(test): restore pruned live boot entries and verify mounted ESP

This commit is contained in:
Codex
2026-10-13 23:31:14 +03:00
parent ce04318b78
commit ebeebc7fb1
4 changed files with 289 additions and 16 deletions
+3 -2
View File
@@ -651,8 +651,9 @@ def qemu_argv(qemu, scratch, disk, code, variables, iso, memory, *, keep_cdrom_d
if not Path(iso).is_file():
raise SmokeError('Trusted ISO must exist as a regular file')
if keep_cdrom_drive:
# Keep one SATA0 device even without media so OVMF retains its DVD boot
# entry across ISO-free boots. No file= means there is no optical medium.
# Keep SATA0 stable so a saved DVD boot option has the same device path
# when media returns. OVMF may still prune the empty drive's boot entry.
# No file= means there is no optical medium.
optical = 'if=ide,index=0,id=acceptance-cdrom,media=cdrom,readonly=on'
if iso is not None:
optical += ',format=raw,file=' + qemu_path(iso)
+120 -7
View File
@@ -44,8 +44,11 @@ def argument_parser():
return parser
def verify_preserved(before, after):
for name in ('gpt', 'foreign_sha256', 'foreign_efi', 'boot_order'):
def verify_preserved(before, after, *, firmware_reboot=False):
fields = ('gpt', 'foreign_sha256', 'foreign_efi')
if not firmware_reboot:
fields += ('boot_order',)
for name in fields:
if before[name] != after[name]:
raise SmokeError('Preserved installation changed ' + name)
@@ -137,6 +140,72 @@ def sha(path):
def tree(path):
return {str(p.relative_to(path)): sha(p) for p in sorted(path.rglob('*')) if p.is_file()}
EFI_GUID = '8be4df61-93ca-11d2-aa0d-00e098032b8c'
DVD_LABEL = 'UEFI QEMU DVD-ROM QM00001'
def efi_description(data):
# The file starts with efivarfs attributes, EFI_LOAD_OPTION attributes and
# FilePathListLength, followed by a bounded UTF-16 description.
for end in range(10, min(len(data) - 1, 522), 2):
if data[end:end + 2] == b'\0\0':
try: return data[10:end].decode('utf-16-le').strip(), end + 2
except UnicodeDecodeError: break
return None, None
def validate_dvd_variable(data):
label, offset = efi_description(data)
path = bytes.fromhex('02010c00d041030a0000000001010600021f03120a000000ffff00007fff0400')
automatic = bytes.fromhex('4eac0881119f594d850ee21a522c59b2')
if (len(data) > 512 or data[:10] != bytes.fromhex('07000000010000002000')
or label != DVD_LABEL or data[offset:offset + 32] != path
or data[offset + 32:] not in (b'', automatic)):
raise RuntimeError('Invalid saved SATA0 DVD EFI load option')
def dvd_variables(variables):
matches = []
for path in variables.glob('Boot????-' + EFI_GUID):
if not re.fullmatch('Boot[0-9A-Fa-f]{4}-' + EFI_GUID, path.name): continue
data = path.read_bytes()
if efi_description(data)[0] == DVD_LABEL:
validate_dvd_variable(data)
matches.append((path.name[4:8], data))
if len(matches) > 1: raise RuntimeError('Ambiguous DVD EFI load options')
return matches
def capture_dvd_variable(variables):
matches = dvd_variables(variables)
if len(matches) != 1: raise RuntimeError('Expected one active SATA0 DVD EFI load option')
entry, data = matches[0]
current = (variables / ('BootCurrent-' + EFI_GUID)).read_bytes()
if len(current) != 6 or int.from_bytes(current[4:], 'little') != int(entry, 16):
raise RuntimeError('Initial live system did not boot from the captured DVD entry')
return {'entry': entry, 'raw_hex': data.hex(), 'sha256': hashlib.sha256(data).hexdigest()}
def restore_dvd_variable(variables, data):
validate_dvd_variable(data)
order = variables / ('BootOrder-' + EFI_GUID)
before = order.read_bytes()
matches = dvd_variables(variables)
created = not matches
if matches:
entry, existing = matches[0]
if existing != data: raise RuntimeError('Existing DVD option differs from captured bytes')
else:
occupied = {int(p.name[4:8], 16) for p in variables.glob('Boot????-' + EFI_GUID)
if re.fullmatch('Boot[0-9A-Fa-f]{4}-' + EFI_GUID, p.name)}
free = next((number for number in range(65536) if number not in occupied), None)
if free is None: raise RuntimeError('No unused UEFI boot variable')
entry = f'{free:04X}'
path = variables / ('Boot' + entry + '-' + EFI_GUID)
# Never overwrite an existing entry, including a concurrently created one.
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)
with os.fdopen(fd, 'wb', buffering=0) as target:
if target.write(data) != len(data): raise RuntimeError('Short EFI variable write')
if path.read_bytes() != data: raise RuntimeError('Saved DVD variable readback mismatch')
if order.read_bytes() != before: raise RuntimeError('DVD variable creation changed BootOrder')
return {'entry': entry, 'created': created, 'sha256': hashlib.sha256(data).hexdigest(),
'boot_order_sha256': hashlib.sha256(before).hexdigest()}
@contextlib.contextmanager
def mounted(device, filesystem, options=''):
import tempfile
@@ -146,10 +215,35 @@ def mounted(device, filesystem, options=''):
try: yield Path(directory)
finally: run('umount', directory)
def installed_esp(marker):
mounts = json.loads(run('findmnt', '--json', '--mountpoint', '/boot/efi', '--output',
'SOURCE,TARGET,FSTYPE,UUID,MAJ:MIN'))['filesystems']
devices = json.loads(run('lsblk', '--json', '--nodeps', '--output',
'NAME,MAJ:MIN,FSTYPE,UUID', '/dev/vda1'))['blockdevices']
if len(mounts) != 1 or len(devices) != 1:
raise RuntimeError('Expected one mounted installed ESP and one test ESP device')
mount, device = mounts[0], devices[0]
if (mount.get('source') != '/dev/vda1' or mount.get('target') != '/boot/efi'
or mount.get('fstype') != 'vfat' or device.get('name') != 'vda1'
or device.get('fstype') != 'vfat' or not device.get('maj:min')
or mount.get('maj:min') != device['maj:min'] or not device.get('uuid')
or mount.get('uuid') != device['uuid'] or marker.get('esp_uuid') != device['uuid']):
raise RuntimeError('Installed ESP mount/device identity does not match the storage marker')
return Path('/boot/efi')
@contextlib.contextmanager
def readonly_esp():
if Path('/etc/hydra/live-mode/active').exists():
with mounted('/dev/vda1', 'vfat', 'ro') as esp: yield esp
else:
# The installed ESP is already mounted rw by fstab. Verify it, then only
# read hashes; a second ro mount would conflict with its superblock state.
yield installed_esp(json.loads(Path('/etc/hydra/storage.json').read_text()))
def preserved():
table = json.loads(run('sfdisk', '--json', '/dev/vda'))['partitiontable']
# No filesystem UUIDs: selected root UUID must change on formatting.
with mounted('/dev/vda1', 'vfat', 'ro') as esp:
with readonly_esp() as esp:
foreign = {k: v for k, v in tree(esp / 'EFI').items() if not k.startswith('HydraOS/')}
order = re.search(r'^BootOrder:\s*(.*)$', run('efibootmgr'), re.M)
assert order, 'UEFI BootOrder was not observable'
@@ -202,6 +296,8 @@ def stop_child(source):
'''
GUEST_BODIES = {
'capture-live-boot': "result = capture_dvd_variable(Path('/sys/firmware/efi/efivars'))\n",
'restore-live-boot': "result = restore_dvd_variable(Path('/sys/firmware/efi/efivars'), bytes.fromhex(context['dvd_variable']))\n",
'seed': r'''
# Guest-only target is the new empty disk attached by this harness.
assert os.geteuid() == 0 and Path('/etc/hydra/live-mode/active').exists()
@@ -263,7 +359,7 @@ assert marker['root_subvolume'] == '@root'
assert Path('/home/hydratest/acceptance-home').read_text() == 'current-' + context['sentinel']
assert not Path('/var/db/pkg/app-misc/hydra-acceptance-2.0').exists()
assert Path('/usr/share/hydra/base-fixture.txt').read_text().strip() == '1.0'
with mounted('/dev/vda1', 'vfat', 'ro') as esp: result = base_state(Path('/'), esp)
with readonly_esp() as esp: result = base_state(Path('/'), esp)
result['home'] = Path('/home/hydratest/acceptance-home').read_text()
result['vm_data'] = tree(Path('/home/hydratest/.local/share/hydra/acceptance-guest'))
result['root_mount'] = run('findmnt', '-n', '-o', 'SOURCE,OPTIONS', '/')
@@ -417,7 +513,8 @@ def main(argv=None):
inputs = {str(p): iso_smoke.digest(p) for p in (args.iso, args.ovmf_code, args.ovmf_vars)}
report = {'schema': 1, 'status': 'running', 'inputs_sha256': inputs, 'checks': {},
'physical_hardware': 'pending', 'kernel_scope': 'exact kernel restoration; no two-kernel upgrade claim',
'trust_scope': 'disposable TEST key temporarily pinned only in this disposable installed guest'}
'trust_scope': 'disposable TEST key temporarily pinned only in this disposable installed guest',
'firmware_scope': 'BootOrder checked around each installer/checkpoint/restore/selector operation; firmware may prune empty-media entries between boots'}
context = {'sentinel': secrets.token_hex(32)}
password = secrets.token_urlsafe(24); vm = None; server = None
def record(name, evidence):
@@ -456,6 +553,8 @@ def main(argv=None):
threading.Thread(target=server.serve_forever, daemon=True).start()
console = boot(True, 'live-install')
before = probe(console, 'seed', context); record('seeded_foreign_invariants', before)
live_boot = probe(console, 'capture-live-boot', context)
context['dvd_variable'] = live_boot['raw_hex']; record('captured_live_boot_option', live_boot)
token = secrets.token_hex(12); console.buffer = b''
console.send(partition_installer_command(token) + '\n')
console.expect_installer(rb'Installed account password: ', 120, token); console.send(password + '\n')
@@ -472,8 +571,11 @@ def main(argv=None):
iso_smoke.installed_admin(console, password)
baseline = probe(console, 'baseline', context, 720); record('real_portage_baseline_doctor_vmdata', baseline)
record('signed_runtime_update_recovery', probe(console, 'runtime', context, 300))
record('harness_checkpoint_dvd_option', probe(console, 'restore-live-boot', context))
record('harness_checkpoint_bootnext', select_live(console)); shutdown(console)
console = boot(True, 'live-checkpoint')
checkpoint_preserved = probe(console, 'preserved', context)
verify_preserved(before, checkpoint_preserved, firmware_reboot=True)
base_before = probe(console, 'base-state', context); record('base_before_checkpoint', base_before)
context['root_uuid'] = console.command('sudo -n blkid -s UUID -o value /dev/vda3').decode().strip()
esp_partuuid = console.command('sudo -n blkid -s PARTUUID -o value /dev/vda1').decode().strip()
@@ -483,10 +585,16 @@ def main(argv=None):
cp = json.loads(console.command(command + ' --execute --confirm-root-uuid ' + shlex.quote(context['root_uuid']), 300))
context['checkpoint'] = cp['id']; record('real_offline_checkpoint', cp)
record('checkpoint_list', json.loads(console.command('sudo -n hydra-system list --root-uuid ' + shlex.quote(context['root_uuid']), 180)))
checkpoint_after = probe(console, 'preserved', context)
verify_preserved(checkpoint_preserved, checkpoint_after)
record('checkpoint_preserved_firmware_and_data', checkpoint_after)
select_installed(console, recreate=True); shutdown(console)
console = boot(False, 'installed-upgrade'); record('real_portage_upgrade_current_home', probe(console, 'upgrade', context, 720))
record('harness_restore_dvd_option', probe(console, 'restore-live-boot', context))
record('harness_restore_bootnext', select_live(console)); shutdown(console)
console = boot(True, 'live-restore')
restore_preserved = probe(console, 'preserved', context)
verify_preserved(before, restore_preserved, firmware_reboot=True)
record('deliberate_kernel_efi_damage', probe(console, 'damage', context))
record('restore_sigkill_real_btrfs', probe(console, 'restore-interrupt', context, 300))
restore = ('sudo -n hydra-system restore --root-uuid ' + shlex.quote(context['root_uuid']) +
@@ -495,13 +603,18 @@ def main(argv=None):
record('fresh_process_restore_resume', json.loads(console.command(restore, 300)))
base_after = probe(console, 'base-state', context)
if base_after != base_before: raise SmokeError('Offline restore did not restore exact base/Portage/kernel/ownedEFI hashes')
preserved_after = probe(console, 'preserved', context); verify_preserved(before, preserved_after)
preserved_after = probe(console, 'preserved', context)
verify_preserved(restore_preserved, preserved_after)
verify_preserved(before, preserved_after, firmware_reboot=True)
record('restored_base_foreign_invariants', {'base': base_after, 'preserved': preserved_after})
select_installed(console, recreate=True); shutdown(console)
console = boot(False, 'installed-restored'); restored = probe(console, 'restored', context)
if any(restored[k] != v for k, v in base_before.items()): raise SmokeError('Disk-only boot did not retain restored base')
if restored['vm_data'] != baseline['vm_data']: raise SmokeError('VM disk/profile bytes changed')
record('disk_only_restored_boot_current_home_vmdata', restored); shutdown(console)
record('disk_only_restored_boot_current_home_vmdata', restored)
final_preserved = probe(console, 'preserved', context)
verify_preserved(before, final_preserved, firmware_reboot=True)
record('final_disk_boot_foreign_invariants', final_preserved); shutdown(console)
if any(iso_smoke.digest(Path(path)) != digest for path, digest in inputs.items()): raise SmokeError('Input ISO/firmware changed')
report['status'] = 'passed'; return 0
except (SmokeError, OSError, ValueError, subprocess.SubprocessError, iso_smoke.QMPError) as exc: