mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-20 21:27:32 +00:00
cache integrity: handle interference from old versions
This commit is contained in:
parent
50ac9d914d
commit
d35d388d9c
2 changed files with 33 additions and 4 deletions
|
@ -240,6 +240,7 @@ def create(self):
|
|||
config.set('cache', 'repository', self.repository.id_str)
|
||||
config.set('cache', 'manifest', '')
|
||||
config.add_section('integrity')
|
||||
config.set('integrity', 'manifest', '')
|
||||
with SaveFile(self.config_path) as fd:
|
||||
config.write(fd)
|
||||
|
||||
|
@ -256,11 +257,19 @@ def load(self):
|
|||
self.manifest_id = unhexlify(self._config.get('cache', 'manifest'))
|
||||
self.timestamp = self._config.get('cache', 'timestamp', fallback=None)
|
||||
self.key_type = self._config.get('cache', 'key_type', fallback=None)
|
||||
if not self._config.has_section('integrity'):
|
||||
self._config.add_section('integrity')
|
||||
try:
|
||||
self.integrity = dict(self._config.items('integrity'))
|
||||
if self._config.get('cache', 'manifest') != self.integrity.pop('manifest'):
|
||||
# The cache config file is updated (parsed with ConfigParser, the state of the ConfigParser
|
||||
# is modified and then written out.), not re-created.
|
||||
# Thus, older versions will leave our [integrity] section alone, making the section's data invalid.
|
||||
# Therefore, we also add the manifest ID to this section and
|
||||
# can discern whether an older version interfere by comparing the manifest IDs of this section
|
||||
# and the main [cache] section.
|
||||
self.integrity = {}
|
||||
logger.warning('Cache integrity data lost: old Borg version modified the cache.')
|
||||
except configparser.NoSectionError:
|
||||
logger.debug('Cache integrity: No integrity data found (files, chunks). Cache is from old version.')
|
||||
self.integrity = {}
|
||||
previous_location = self._config.get('cache', 'previous_location', fallback=None)
|
||||
if previous_location:
|
||||
|
@ -272,11 +281,14 @@ def save(self, manifest=None, key=None):
|
|||
if manifest:
|
||||
self._config.set('cache', 'manifest', manifest.id_str)
|
||||
self._config.set('cache', 'timestamp', manifest.timestamp)
|
||||
if not self._config.has_section('integrity'):
|
||||
self._config.add_section('integrity')
|
||||
for file, integrity_data in self.integrity.items():
|
||||
self._config.set('integrity', file, integrity_data)
|
||||
self._config.set('integrity', 'manifest', manifest.id_str)
|
||||
if key:
|
||||
self._config.set('cache', 'key_type', str(key.TYPE))
|
||||
self._config.set('cache', 'previous_location', self.repository._location.canonical_path())
|
||||
for file, integrity_data in self.integrity.items():
|
||||
self._config.set('integrity', file, integrity_data)
|
||||
with SaveFile(self.config_path) as fd:
|
||||
self._config.write(fd)
|
||||
|
||||
|
|
|
@ -2949,6 +2949,23 @@ def test_chunks_archive(self):
|
|||
assert 'Cached archive chunk index of test1 is corrupted' in out
|
||||
assert 'Fetching and building archive index for test1' in out
|
||||
|
||||
def test_old_version_intefered(self):
|
||||
self.create_test_files()
|
||||
self.cmd('init', '--encryption=repokey', self.repository_location)
|
||||
cache_path = json.loads(self.cmd('info', self.repository_location, '--json'))['cache']['path']
|
||||
|
||||
# Modify the main manifest ID without touching the manifest ID in the integrity section.
|
||||
# This happens if a version without integrity checking modifies the cache.
|
||||
config_path = os.path.join(cache_path, 'config')
|
||||
config = ConfigParser(interpolation=None)
|
||||
config.read(config_path)
|
||||
config.set('cache', 'manifest', bin_to_hex(bytes(32)))
|
||||
with open(config_path, 'w') as fd:
|
||||
config.write(fd)
|
||||
|
||||
out = self.cmd('info', self.repository_location)
|
||||
assert 'Cache integrity data lost: old Borg version modified the cache.' in out
|
||||
|
||||
|
||||
class DiffArchiverTestCase(ArchiverTestCaseBase):
|
||||
def test_basic_functionality(self):
|
||||
|
|
Loading…
Reference in a new issue