Reject ambiguous ESP filesystem UUIDs before root formatting
This commit is contained in:
@@ -118,6 +118,14 @@ def partition_plan(request, probe, topo):
|
||||
fail('ESP must be an existing FAT GPT EFI System Partition')
|
||||
if not UUID.fullmatch(esp_node.get('uuid') or ''):
|
||||
fail('ESP filesystem UUID missing')
|
||||
# fstab resolves the ESP by filesystem UUID. Copies on any surviving
|
||||
# device are ambiguous even when their GPT partition identities differ.
|
||||
# Root's old filesystem is replaced before fstab is written.
|
||||
copies = [path for path, node in topo.nodes.items()
|
||||
if path not in {root, esp}
|
||||
and (node.get('uuid') or '').lower() == esp_node['uuid'].lower()]
|
||||
if copies:
|
||||
fail('ESP filesystem UUID is ambiguous on surviving devices: ' + ', '.join(sorted(copies)))
|
||||
# Equal GPT IDs anywhere would make later PARTUUID recovery ambiguous.
|
||||
ids = [n.get('partuuid', '').lower() for n in topo.nodes.values() if n.get('partuuid')]
|
||||
if len(ids) != len(set(ids)):
|
||||
|
||||
@@ -108,6 +108,23 @@ class PartitionGuardTests(unittest.TestCase):
|
||||
def test_explicit_partitions_allow_unrelated_mounted_sibling(self):
|
||||
self.assertEqual(i.validate_request(partition_request(), FakeProbe(partition_topology(sibling_mounted=True))), '/dev/vda2')
|
||||
|
||||
def test_duplicate_esp_uuid_on_surviving_devices_is_refused(self):
|
||||
for location in ('sibling', 'other-disk'):
|
||||
for copied_uuid in ('ABCD-1234', 'abcd-1234'):
|
||||
topo = partition_topology()
|
||||
if location == 'sibling':
|
||||
copied = topo.nodes['/dev/vda3']
|
||||
else:
|
||||
copied = disk('/dev/vdb1', kind='part', pkname='/dev/vdb')
|
||||
copied.update(start=2048, size=1024**3,
|
||||
partuuid='bbbbbbbb-cccc-dddd-eeee-000000000001')
|
||||
topo = topology(topo.nodes['/dev/vda'], disk('/dev/vdb', children=[copied]))
|
||||
copied = topo.nodes['/dev/vdb1']
|
||||
copied.update(fstype='vfat', uuid=copied_uuid,
|
||||
parttype='c12a7328-f81f-11d2-ba4b-00a0c93ec93b')
|
||||
with self.subTest(location=location, uuid=copied_uuid), self.assertRaisesRegex(i.InstallError, 'ESP filesystem UUID'):
|
||||
i.validate_request(partition_request(), FakeProbe(topo))
|
||||
|
||||
def test_modes_and_confirmations_are_unambiguous(self):
|
||||
for changes in ({'disk': '/dev/vda'}, {'esp_partition': None}, {'root_fs': 'xfs'},
|
||||
{'confirm_erase': '/dev/vda'}, {'confirm_format': '/dev/vda3', 'execute': True}):
|
||||
@@ -251,6 +268,17 @@ class PartitionPipelineTests(unittest.TestCase):
|
||||
def install(self, runner):
|
||||
i.install(self.request, runner, self.probe, self.root, 'test-password', io.StringIO())
|
||||
|
||||
def test_duplicate_fat_uuid_with_distinct_partuuid_stops_before_root_format(self):
|
||||
copied = self.probe.topo.nodes['/dev/vda3']
|
||||
copied.update(fstype='vfat', uuid='ABCD-1234',
|
||||
parttype='c12a7328-f81f-11d2-ba4b-00a0c93ec93b')
|
||||
self.assertNotEqual(copied['partuuid'], self.probe.topo.nodes['/dev/vda1']['partuuid'])
|
||||
runner = FakeRunner(self.root)
|
||||
with self.assertRaisesRegex(i.InstallError, 'ESP filesystem UUID'):
|
||||
self.install(runner)
|
||||
self.assertEqual(runner.calls, [])
|
||||
self.assertFalse((self.root/'etc/fstab').exists())
|
||||
|
||||
def test_existing_mode_formats_root_only_and_records_owned_layout(self):
|
||||
runner = FakeRunner(self.root)
|
||||
self.install(runner)
|
||||
|
||||
Reference in New Issue
Block a user