From 577428f1b20da6f7f583c9c3c276ee1d38abb01d Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:13:08 +0100 Subject: Added a partition.umount() and a check when running cryptsetup if the disk is in use. --- archinstall/lib/luks.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/luks.py') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index e54641b8..de53c05e 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -64,8 +64,14 @@ class luks2(): with open(key_file, 'wb') as fh: fh.write(password) - o = b''.join(sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}')) - if b'Command successful.' not in o: + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + if cmd_handle.exit_code == 256: + # Partition was in use, unmount it and + partition.unmount() + sys_command(f'cryptsetup close {partition.path}') + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + + if b'Command successful.' not in b''.join(cmd_handle): raise DiskError(f'Could not encrypt volume "{partition.path}": {o}') return key_file -- cgit v1.2.3-70-g09d2 From f589750a3cff6f061bc4b78ef857e52a7fbc874c Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:16:46 +0100 Subject: Tweaked SysCallError() exception to include the exit code in a machine readable manner. Since it's useful as an indicator where calls might go wrong and for what reason. --- archinstall/lib/exceptions.py | 5 ++++- archinstall/lib/general.py | 2 +- archinstall/lib/luks.py | 14 +++++++++----- 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'archinstall/lib/luks.py') diff --git a/archinstall/lib/exceptions.py b/archinstall/lib/exceptions.py index 5a5d47c6..558a397d 100644 --- a/archinstall/lib/exceptions.py +++ b/archinstall/lib/exceptions.py @@ -7,7 +7,10 @@ class UnknownFilesystemFormat(BaseException): class ProfileError(BaseException): pass class SysCallError(BaseException): - pass + def __init__(self, message, error_code): + super(SysCallError, self).__init__(message) + self.message = message + self.error_code = error_code class ProfileNotFound(BaseException): pass class HardwareIncompatibilityError(BaseException): diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index e87e4102..28fc0934 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -251,7 +251,7 @@ class sys_command():#Thread): if self.exit_code != 0 and not self.kwargs['suppress_errors']: #self.log(self.trace_log.decode('UTF-8'), level=LOG_LEVELS.Debug) #self.log(f"'{self.raw_cmd}' did not exit gracefully, exit code {self.exit_code}.", level=LOG_LEVELS.Error) - raise SysCallError(f"{self.trace_log.decode('UTF-8')}\n'{self.raw_cmd}' did not exit gracefully (trace log above), exit code: {self.exit_code}") + raise SysCallError(message=f"{self.trace_log.decode('UTF-8')}\n'{self.raw_cmd}' did not exit gracefully (trace log above), exit code: {self.exit_code}", exit_code=self.exit_code) self.ended = time.time() with open(f'{self.cwd}/trace.log', 'wb') as fh: diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index de53c05e..a4d2a07d 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -64,12 +64,16 @@ class luks2(): with open(key_file, 'wb') as fh: fh.write(password) - cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') - if cmd_handle.exit_code == 256: - # Partition was in use, unmount it and - partition.unmount() - sys_command(f'cryptsetup close {partition.path}') + try: cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + except SysCallError as err: + if err.exit_code == 256: + # Partition was in use, unmount it and try again + partition.unmount() + sys_command(f'cryptsetup close {partition.path}') + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') + else: + raise err if b'Command successful.' not in b''.join(cmd_handle): raise DiskError(f'Could not encrypt volume "{partition.path}": {o}') -- cgit v1.2.3-70-g09d2 From e4514e8fc37995656528835d4fd81dc997136575 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:27:48 +0100 Subject: Some more error handling. --- archinstall/lib/luks.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'archinstall/lib/luks.py') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index a4d2a07d..77622304 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -70,7 +70,14 @@ class luks2(): if err.exit_code == 256: # Partition was in use, unmount it and try again partition.unmount() - sys_command(f'cryptsetup close {partition.path}') + try: + sys_command(f'cryptsetup close {partition.path}') + except SysCallError as err: + # 0 Means everything went smoothly, + # 1024 means the device was not found. + if err.exit_code not in (0, 1024): + raise err + cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') else: raise err -- cgit v1.2.3-70-g09d2 From 1c6d70571481e30651f62f216fcc9653e03c9c62 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 12:50:47 +0100 Subject: Enhanced the error handling on crypt-devices. --- archinstall/lib/luks.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'archinstall/lib/luks.py') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 77622304..f4c787ab 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -65,19 +65,28 @@ class luks2(): fh.write(password) try: + # Try to setup the crypt-device cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') except SysCallError as err: if err.exit_code == 256: # Partition was in use, unmount it and try again partition.unmount() - try: - sys_command(f'cryptsetup close {partition.path}') - except SysCallError as err: - # 0 Means everything went smoothly, - # 1024 means the device was not found. - if err.exit_code not in (0, 1024): - raise err + # Get crypt-information about the device by doing a reverse lookup starting with the partition path + # For instance: /dev/sda + devinfo = json.loads(b''.join(sys_command(f"lsblk --fs -J {partition.path}")).decode('UTF-8'))['blockdevices'][0] + + # For each child (sub-partition/sub-device) + if len(children := devinfo.get('children', [])): + for child in children: + # Unmount the child location + if child_mountpoint := child.get('mountpoint', None): + sys_command(f"umount {child_mountpoint}") + + # And close it if possible. + sys_command(f"cryptsetup close {child['name']}") + + # Then try again to set up the crypt-device cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') else: raise err -- cgit v1.2.3-70-g09d2 From 7ac68b2436b3a542d8004b26defb89ebb2905fa9 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 13:54:01 +0100 Subject: Removed redundant error handling as well as added some more debug logs. --- archinstall/lib/luks.py | 3 +++ examples/guided.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'archinstall/lib/luks.py') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index f4c787ab..ff5e2057 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -69,6 +69,7 @@ class luks2(): cmd_handle = sys_command(f'/usr/bin/cryptsetup -q -v --type luks2 --pbkdf argon2i --hash {hash_type} --key-size {key_size} --iter-time {iter_time} --key-file {os.path.abspath(key_file)} --use-urandom luksFormat {partition.path}') except SysCallError as err: if err.exit_code == 256: + log(f'{partition} is being used, trying to unmount and crypt-close the device and running one more attempt at encrypting the device.', level=LOG_LEVELS.Debug) # Partition was in use, unmount it and try again partition.unmount() @@ -81,9 +82,11 @@ class luks2(): for child in children: # Unmount the child location if child_mountpoint := child.get('mountpoint', None): + log(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug) sys_command(f"umount {child_mountpoint}") # And close it if possible. + log(f"Closing crypt device {child['name']}", level=LOG_LEVELS.Debug) sys_command(f"cryptsetup close {child['name']}") # Then try again to set up the crypt-device diff --git a/examples/guided.py b/examples/guided.py index 9339f969..74d413aa 100644 --- a/examples/guided.py +++ b/examples/guided.py @@ -305,8 +305,8 @@ def perform_installation(device, boot_partition, language, mirrors): if archinstall.arguments.get('packages', None) and archinstall.arguments.get('packages', None)[0] != '': installation.add_additional_packages(archinstall.arguments.get('packages', None)) - if archinstall.arguments.get('profile', None) and len(profile := archinstall.arguments.get('profile').strip()): - installation.install_profile(profile) + if archinstall.arguments.get('profile', None): + installation.install_profile(archinstall.arguments.get('profile', None)) if archinstall.arguments.get('users', None): for user in archinstall.arguments.get('users'): -- cgit v1.2.3-70-g09d2 From c897421e1d5450450e0ef54118ad40c1d883b7c3 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Sun, 14 Mar 2021 13:56:24 +0100 Subject: Using 'umount -R' rather than just 'umount' since we're going to wipe the partition, we need do unmount anything that's mounted beneeth it to continue. --- archinstall/lib/luks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'archinstall/lib/luks.py') diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index ff5e2057..30c38ec8 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -83,7 +83,7 @@ class luks2(): # Unmount the child location if child_mountpoint := child.get('mountpoint', None): log(f'Unmounting {child_mountpoint}', level=LOG_LEVELS.Debug) - sys_command(f"umount {child_mountpoint}") + sys_command(f"umount -R {child_mountpoint}") # And close it if possible. log(f"Closing crypt device {child['name']}", level=LOG_LEVELS.Debug) -- cgit v1.2.3-70-g09d2 From 5e9c973d42125bb809443670c1e30439e4b11b17 Mon Sep 17 00:00:00 2001 From: Anton Hvornum Date: Mon, 29 Mar 2021 16:51:30 +0200 Subject: Added support for flushing a BlockDevice() cache after a partition has been formatted. This is to avoid internal confusion of which partitions are encrypted or not when going from Encrypted -> Un-encrypted setups. --- archinstall/lib/disk.py | 11 +++++++++-- archinstall/lib/luks.py | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'archinstall/lib/luks.py') diff --git a/archinstall/lib/disk.py b/archinstall/lib/disk.py index 0e42feca..518c1503 100644 --- a/archinstall/lib/disk.py +++ b/archinstall/lib/disk.py @@ -107,7 +107,7 @@ class BlockDevice(): if part_id not in self.part_cache: ## TODO: Force over-write even if in cache? if part_id not in self.part_cache or self.part_cache[part_id].size != part['size']: - self.part_cache[part_id] = Partition(root_path + part_id, part_id=part_id, size=part['size']) + self.part_cache[part_id] = Partition(root_path + part_id, self, part_id=part_id, size=part['size']) return {k: self.part_cache[k] for k in sorted(self.part_cache)} @@ -133,9 +133,11 @@ class BlockDevice(): self.part_cache = OrderedDict() class Partition(): - def __init__(self, path, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): + def __init__(self, path :str, block_device :BlockDevice, part_id=None, size=-1, filesystem=None, mountpoint=None, encrypted=False, autodetect_filesystem=True): if not part_id: part_id = os.path.basename(path) + + self.block_device = block_device self.path = path self.part_id = part_id self.mountpoint = mountpoint @@ -192,6 +194,7 @@ class Partition(): if value: log(f'Marking {self} as encrypted: {value}', level=LOG_LEVELS.Debug) log(f"Callstrack when marking the partition: {''.join(traceback.format_stack())}", level=LOG_LEVELS.Debug) + self._encrypted = value @property @@ -318,6 +321,10 @@ class Partition(): else: raise UnknownFilesystemFormat(f"Fileformat '{filesystem}' is not yet implemented.") + + if self.block_device: + self.block_device.flush_cache() + return True def find_parent_of(self, data, name, parent=None): diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 30c38ec8..19c21795 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -113,7 +113,7 @@ class luks2(): sys_command(f'/usr/bin/cryptsetup open {partition.path} {mountpoint} --key-file {os.path.abspath(key_file)} --type luks2') if os.path.islink(f'/dev/mapper/{mountpoint}'): self.mapdev = f'/dev/mapper/{mountpoint}' - unlocked_partition = Partition(self.mapdev, encrypted=True, filesystem=get_filesystem_type(self.mapdev), autodetect_filesystem=False) + unlocked_partition = Partition(self.mapdev, None, encrypted=True, filesystem=get_filesystem_type(self.mapdev), autodetect_filesystem=False) unlocked_partition.allow_formatting = self.partition.allow_formatting return unlocked_partition -- cgit v1.2.3-70-g09d2