In integrity violations, use individual messages saying which check exactly failed.

This commit is contained in:
Sebastian Messmer 2016-06-25 16:43:37 -07:00
parent f066b45954
commit 1c654305a8
4 changed files with 16 additions and 10 deletions

View File

@ -10,15 +10,20 @@ namespace blockstore {
class IntegrityViolationError final : public std::exception {
public:
IntegrityViolationError(const std::string &reason)
: _reason("Integrity violation: " + reason) {
}
const char *what() const throw() override {
return _reason.c_str();
}
private:
// Constructor is private to make sure that only VersionCountingBlockStore can throw this exception.
// This is because VersionCountingBlockStore wants to know about integrity violations and
// block all further file system access if it happens.
IntegrityViolationError(const std::string &reason)
: _reason("Integrity violation: " + reason) {
}
friend class VersionCountingBlockStore;
std::string _reason;
};

View File

@ -114,7 +114,7 @@ inline void VersionCountingBlock::_checkVersion() {
uint32_t lastClientId = _readClientId();
uint64_t version = _readVersion();
if(!_blockStore->knownBlockVersions()->checkAndUpdateVersion(lastClientId, key(), version)) {
_blockStore->integrityViolationDetected();
_blockStore->integrityViolationDetected("The block version number is too low. Did an attacker try to roll back the block or to re-introduce a deleted block?");
}
}

View File

@ -7,6 +7,7 @@ using cpputils::make_unique_ref;
using cpputils::Data;
using boost::none;
using boost::optional;
using std::string;
namespace bf = boost::filesystem;
namespace blockstore {
@ -35,7 +36,7 @@ namespace blockstore {
auto block = _baseBlockStore->load(key);
if (block == boost::none) {
if (_missingBlockIsIntegrityViolation && _knownBlockVersions.blockShouldExist(key)) {
integrityViolationDetected();
integrityViolationDetected("A block that should exist wasn't found. Did an attacker delete it?");
}
return boost::none;
}
@ -52,9 +53,9 @@ namespace blockstore {
}
}
void VersionCountingBlockStore::integrityViolationDetected() {
void VersionCountingBlockStore::integrityViolationDetected(const string &reason) const {
_integrityViolationDetected = true;
throw IntegrityViolationError("A block that should exist wasn't found. Did an attacker delete it?");
throw IntegrityViolationError(reason);
}
void VersionCountingBlockStore::remove(unique_ref<Block> block) {
@ -93,7 +94,7 @@ namespace blockstore {
}
});
if (!existingBlocks.empty()) {
throw IntegrityViolationError("A block that should have existed wasn't found.");
integrityViolationDetected("A block that should have existed wasn't found.");
}
}

View File

@ -24,7 +24,7 @@ public:
uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override;
void integrityViolationDetected();
void integrityViolationDetected(const std::string &reason) const;
KnownBlockVersions *knownBlockVersions();
#ifndef CRYFS_NO_COMPATIBILITY
@ -35,7 +35,7 @@ private:
cpputils::unique_ref<BlockStore> _baseBlockStore;
KnownBlockVersions _knownBlockVersions;
const bool _missingBlockIsIntegrityViolation;
bool _integrityViolationDetected;
mutable bool _integrityViolationDetected;
void _checkNoPastIntegrityViolations();