From 151fe5f3483ad0bcb4b1455e5c451b80b66cd684 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 7 Apr 2022 01:22:34 +0200 Subject: [PATCH 1/2] check archive: make robust_iterator more robust, fixes #4777 borg check must not crash if an archive metadata chunk does not decrypt. Instead, report the chunk and skip to the next one. --- src/borg/archive.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index 0f0c8ffb4..f7b6b4703 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -1937,20 +1937,25 @@ class ArchiveChecker: if state > 0: unpacker.resync() for chunk_id, cdata in zip(items, repository.get_many(items)): - data = self.key.decrypt(chunk_id, cdata) - unpacker.feed(data) try: + data = self.key.decrypt(chunk_id, cdata) + unpacker.feed(data) for item in unpacker: valid, reason = valid_item(item) if valid: yield Item(internal_dict=item) else: report('Did not get expected metadata dict when unpacking item metadata (%s)' % reason, chunk_id, i) + except IntegrityError as integrity_error: + # key.decrypt() detected integrity issues. + # maybe the repo gave us a valid cdata, but not for the chunk_id we wanted. + # or the authentication of cdata failed, meaning the encrypted data was corrupted. + report(str(integrity_error), chunk_id, i) except msgpack.UnpackException: report('Unpacker crashed while unpacking item metadata, trying to resync...', chunk_id, i) unpacker.resync() except Exception: - report('Exception while unpacking item metadata', chunk_id, i) + report('Exception while decrypting or unpacking item metadata', chunk_id, i) raise i += 1 From c8f160068ef339fa0a7bd76bd599214b6327fa60 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Thu, 7 Apr 2022 01:35:35 +0200 Subject: [PATCH 2/2] check archives: improve error handling for corrupt archive metadata block this is similar to #4777. borg check must not crash if an archive metadata block does not decrypt. Instead, report the archive_id, remove the archive from the manifest and skip to the next archive. --- src/borg/archive.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/borg/archive.py b/src/borg/archive.py index f7b6b4703..df10e1f1c 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -1989,13 +1989,19 @@ class ArchiveChecker: logger.info(f'Analyzing archive {info.name} ({i + 1}/{num_archives})') archive_id = info.id if archive_id not in self.chunks: - logger.error('Archive metadata block is missing!') + logger.error('Archive metadata block %s is missing!', bin_to_hex(archive_id)) self.error_found = True del self.manifest.archives[info.name] continue mark_as_possibly_superseded(archive_id) cdata = self.repository.get(archive_id) - data = self.key.decrypt(archive_id, cdata) + try: + data = self.key.decrypt(archive_id, cdata) + except IntegrityError as integrity_error: + logger.error('Archive metadata block %s is corrupted: %s', bin_to_hex(archive_id), integrity_error) + self.error_found = True + del self.manifest.archives[info.name] + continue archive = ArchiveItem(internal_dict=msgpack.unpackb(data)) if archive.version != 1: raise Exception('Unknown archive metadata version')