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 { class IntegrityViolationError final : public std::exception {
public: public:
IntegrityViolationError(const std::string &reason)
: _reason("Integrity violation: " + reason) {
}
const char *what() const throw() override { const char *what() const throw() override {
return _reason.c_str(); return _reason.c_str();
} }
private: 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; std::string _reason;
}; };

View File

@ -114,7 +114,7 @@ inline void VersionCountingBlock::_checkVersion() {
uint32_t lastClientId = _readClientId(); uint32_t lastClientId = _readClientId();
uint64_t version = _readVersion(); uint64_t version = _readVersion();
if(!_blockStore->knownBlockVersions()->checkAndUpdateVersion(lastClientId, key(), version)) { 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 cpputils::Data;
using boost::none; using boost::none;
using boost::optional; using boost::optional;
using std::string;
namespace bf = boost::filesystem; namespace bf = boost::filesystem;
namespace blockstore { namespace blockstore {
@ -35,7 +36,7 @@ namespace blockstore {
auto block = _baseBlockStore->load(key); auto block = _baseBlockStore->load(key);
if (block == boost::none) { if (block == boost::none) {
if (_missingBlockIsIntegrityViolation && _knownBlockVersions.blockShouldExist(key)) { if (_missingBlockIsIntegrityViolation && _knownBlockVersions.blockShouldExist(key)) {
integrityViolationDetected(); integrityViolationDetected("A block that should exist wasn't found. Did an attacker delete it?");
} }
return boost::none; return boost::none;
} }
@ -52,9 +53,9 @@ namespace blockstore {
} }
} }
void VersionCountingBlockStore::integrityViolationDetected() { void VersionCountingBlockStore::integrityViolationDetected(const string &reason) const {
_integrityViolationDetected = true; _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) { void VersionCountingBlockStore::remove(unique_ref<Block> block) {
@ -93,7 +94,7 @@ namespace blockstore {
} }
}); });
if (!existingBlocks.empty()) { 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; uint64_t blockSizeFromPhysicalBlockSize(uint64_t blockSize) const override;
void forEachBlock(std::function<void (const Key &)> callback) const override; void forEachBlock(std::function<void (const Key &)> callback) const override;
void integrityViolationDetected(); void integrityViolationDetected(const std::string &reason) const;
KnownBlockVersions *knownBlockVersions(); KnownBlockVersions *knownBlockVersions();
#ifndef CRYFS_NO_COMPATIBILITY #ifndef CRYFS_NO_COMPATIBILITY
@ -35,7 +35,7 @@ private:
cpputils::unique_ref<BlockStore> _baseBlockStore; cpputils::unique_ref<BlockStore> _baseBlockStore;
KnownBlockVersions _knownBlockVersions; KnownBlockVersions _knownBlockVersions;
const bool _missingBlockIsIntegrityViolation; const bool _missingBlockIsIntegrityViolation;
bool _integrityViolationDetected; mutable bool _integrityViolationDetected;
void _checkNoPastIntegrityViolations(); void _checkNoPastIntegrityViolations();