1
0
Fork 0
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:
Marian Beermann 2017-05-25 16:13:40 +02:00
parent 50ac9d914d
commit d35d388d9c
2 changed files with 33 additions and 4 deletions

View file

@ -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)

View file

@ -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):