In integrity violations, use individual messages saying which check exactly failed.
This commit is contained in:
parent
f066b45954
commit
1c654305a8
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user