Do a sanity check when mounting the file system and fail if the root blob is not available.

This commit is contained in:
Sebastian Messmer 2016-02-19 02:10:10 +01:00
parent f134946089
commit d00e097954
5 changed files with 28 additions and 10 deletions

View File

@ -18,6 +18,7 @@
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <gitversion/version.h> #include <gitversion/version.h>
#include <cryfs/filesystem/CryDir.h>
#include "VersionChecker.h" #include "VersionChecker.h"
@ -60,6 +61,7 @@ using boost::chrono::duration;
using boost::chrono::duration_cast; using boost::chrono::duration_cast;
using boost::chrono::minutes; using boost::chrono::minutes;
using boost::chrono::milliseconds; using boost::chrono::milliseconds;
using cpputils::dynamic_pointer_move;
//TODO Delete a large file in parallel possible? Takes a long time right now... //TODO Delete a large file in parallel possible? Takes a long time right now...
//TODO Improve parallelity. //TODO Improve parallelity.
@ -197,6 +199,7 @@ namespace cryfs {
auto blockStore = make_unique_ref<OnDiskBlockStore>(options.baseDir()); auto blockStore = make_unique_ref<OnDiskBlockStore>(options.baseDir());
auto config = _loadOrCreateConfig(options); auto config = _loadOrCreateConfig(options);
CryDevice device(std::move(config), std::move(blockStore)); CryDevice device(std::move(config), std::move(blockStore));
_sanityCheckFilesystem(&device);
fspp::FilesystemImpl fsimpl(&device); fspp::FilesystemImpl fsimpl(&device);
fspp::fuse::Fuse fuse(&fsimpl); fspp::fuse::Fuse fuse(&fsimpl);
@ -223,6 +226,19 @@ namespace cryfs {
} }
} }
void Cli::_sanityCheckFilesystem(CryDevice *device) {
//Try to list contents of base directory
auto _rootDir = device->Load("/"); // this might throw an exception if the root blob doesn't exist
if (_rootDir == none) {
throw std::runtime_error("Couldn't find root blob");
}
auto rootDir = dynamic_pointer_move<CryDir>(*_rootDir);
if (rootDir == none) {
throw std::runtime_error("Base directory blob doesn't contain a directory");
}
(*rootDir)->children(); // Load children
}
optional<unique_ref<CallAfterTimeout>> Cli::_createIdleCallback(optional<double> minutes, function<void()> callback) { optional<unique_ref<CallAfterTimeout>> Cli::_createIdleCallback(optional<double> minutes, function<void()> callback) {
if (minutes == none) { if (minutes == none) {
return none; return none;

View File

@ -9,6 +9,7 @@
#include <cpp-utils/io/Console.h> #include <cpp-utils/io/Console.h>
#include <cpp-utils/random/RandomGenerator.h> #include <cpp-utils/random/RandomGenerator.h>
#include <cpp-utils/network/HttpClient.h> #include <cpp-utils/network/HttpClient.h>
#include <cryfs/filesystem/CryDevice.h>
#include "CallAfterTimeout.h" #include "CallAfterTimeout.h"
namespace cryfs { namespace cryfs {
@ -36,6 +37,7 @@ namespace cryfs {
std::shared_ptr<cpputils::TempFile> _checkDirWriteable(const boost::filesystem::path &dir, const std::string &name); std::shared_ptr<cpputils::TempFile> _checkDirWriteable(const boost::filesystem::path &dir, const std::string &name);
void _checkDirReadable(const boost::filesystem::path &dir, std::shared_ptr<cpputils::TempFile> tempfile, const std::string &name); void _checkDirReadable(const boost::filesystem::path &dir, std::shared_ptr<cpputils::TempFile> tempfile, const std::string &name);
boost::optional<cpputils::unique_ref<CallAfterTimeout>> _createIdleCallback(boost::optional<double> minutes, std::function<void()> callback); boost::optional<cpputils::unique_ref<CallAfterTimeout>> _createIdleCallback(boost::optional<double> minutes, std::function<void()> callback);
void _sanityCheckFilesystem(CryDevice *device);
cpputils::RandomGenerator &_keyGenerator; cpputils::RandomGenerator &_keyGenerator;
cpputils::SCryptSettings _scryptSettings; cpputils::SCryptSettings _scryptSettings;

View File

@ -74,7 +74,7 @@ optional<unique_ref<fspp::Node>> CryDevice::Load(const bf::path &path) {
callFsActionCallbacks(); callFsActionCallbacks();
if (path.parent_path().empty()) { if (path.parent_path().empty()) {
//We are asked to load the root directory '/'. //We are asked to load the base directory '/'.
return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, none, _rootKey)); return optional<unique_ref<fspp::Node>>(make_unique_ref<CryDir>(this, none, _rootKey));
} }
auto parent = LoadDirBlob(path.parent_path()); auto parent = LoadDirBlob(path.parent_path());
@ -165,7 +165,7 @@ unique_ref<SymlinkBlobRef> CryDevice::CreateSymlinkBlob(const bf::path &target)
unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) { unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {
auto blob = _fsBlobStore->load(key); auto blob = _fsBlobStore->load(key);
if (blob == none) { if (blob == none) {
LOG(ERROR) << "Could not load blob " << key.ToString() << ". Is the root directory accessible?"; LOG(ERROR) << "Could not load blob " << key.ToString() << ". Is the base directory accessible?";
throw FuseErrnoException(EIO); throw FuseErrnoException(EIO);
} }
return std::move(*blob); return std::move(*blob);
@ -174,7 +174,7 @@ unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {
void CryDevice::RemoveBlob(const blockstore::Key &key) { void CryDevice::RemoveBlob(const blockstore::Key &key) {
auto blob = _fsBlobStore->load(key); auto blob = _fsBlobStore->load(key);
if (blob == none) { if (blob == none) {
LOG(ERROR) << "Could not load blob " << key.ToString() << ". Is the root directory accessible?"; LOG(ERROR) << "Could not load blob " << key.ToString() << ". Is the base directory accessible?";
throw FuseErrnoException(EIO); throw FuseErrnoException(EIO);
} }
_fsBlobStore->remove(std::move(*blob)); _fsBlobStore->remove(std::move(*blob));

View File

@ -44,7 +44,7 @@ void CryNode::access(int mask) const {
void CryNode::rename(const bf::path &to) { void CryNode::rename(const bf::path &to) {
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
if (_parent == none) { if (_parent == none) {
//We are the root direcory. //We are the base direcory.
//TODO What should we do? //TODO What should we do?
throw FuseErrnoException(EIO); throw FuseErrnoException(EIO);
} }
@ -67,7 +67,7 @@ void CryNode::rename(const bf::path &to) {
void CryNode::utimens(timespec lastAccessTime, timespec lastModificationTime) { void CryNode::utimens(timespec lastAccessTime, timespec lastModificationTime) {
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
if (_parent == none) { if (_parent == none) {
//We are the root direcory. //We are the base direcory.
//TODO What should we do? //TODO What should we do?
throw FuseErrnoException(EIO); throw FuseErrnoException(EIO);
} }
@ -77,7 +77,7 @@ void CryNode::utimens(timespec lastAccessTime, timespec lastModificationTime) {
void CryNode::removeNode() { void CryNode::removeNode() {
//TODO Instead of all these if-else and having _parent being an optional, we could also introduce a CryRootDir which inherits from fspp::Dir. //TODO Instead of all these if-else and having _parent being an optional, we could also introduce a CryRootDir which inherits from fspp::Dir.
if (_parent == none) { if (_parent == none) {
//We are the root direcory. //We are the base direcory.
//TODO What should we do? //TODO What should we do?
throw FuseErrnoException(EIO); throw FuseErrnoException(EIO);
} }
@ -100,7 +100,7 @@ unique_ref<FsBlobRef> CryNode::LoadBlob() const {
void CryNode::stat(struct ::stat *result) const { void CryNode::stat(struct ::stat *result) const {
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
if(_parent == none) { if(_parent == none) {
//We are the root directory. //We are the base directory.
//TODO What should we do? //TODO What should we do?
result->st_uid = getuid(); result->st_uid = getuid();
result->st_gid = getgid(); result->st_gid = getgid();
@ -114,7 +114,7 @@ void CryNode::stat(struct ::stat *result) const {
void CryNode::chmod(mode_t mode) { void CryNode::chmod(mode_t mode) {
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
if (_parent == none) { if (_parent == none) {
//We are the root direcory. //We are the base direcory.
//TODO What should we do? //TODO What should we do?
throw FuseErrnoException(EIO); throw FuseErrnoException(EIO);
} }
@ -124,7 +124,7 @@ void CryNode::chmod(mode_t mode) {
void CryNode::chown(uid_t uid, gid_t gid) { void CryNode::chown(uid_t uid, gid_t gid) {
device()->callFsActionCallbacks(); device()->callFsActionCallbacks();
if (_parent == none) { if (_parent == none) {
//We are the root direcory. //We are the base direcory.
//TODO What should we do? //TODO What should we do?
throw FuseErrnoException(EIO); throw FuseErrnoException(EIO);
} }

View File

@ -275,7 +275,7 @@ int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fil
// On FreeBSD, trying to do anything with the mountpoint ends up // On FreeBSD, trying to do anything with the mountpoint ends up
// opening it, and then using the FD for an fgetattr. So in the // opening it, and then using the FD for an fgetattr. So in the
// special case of a path of "/", I need to do a getattr on the // special case of a path of "/", I need to do a getattr on the
// underlying root directory instead of doing the fgetattr(). // underlying base directory instead of doing the fgetattr().
// TODO Check if necessary // TODO Check if necessary
if (path.native() == "/") { if (path.native() == "/") {
return getattr(path, stbuf); return getattr(path, stbuf);