Merge pull request #125 from ossobv/wjd-refuse_descent_into_own_mountpoint

Perform checks to ensure that we're not descending into ourself.
This commit is contained in:
Valient Gough 2015-11-14 16:03:00 -08:00
commit a461d88cc3
5 changed files with 45 additions and 15 deletions

View File

@ -254,13 +254,9 @@ DirNode::DirNode(EncFS_Context *_ctx, const string &sourceDir,
Lock _lock(mutex);
ctx = _ctx;
rootDir = sourceDir;
rootDir = sourceDir; // .. and fsConfig->opts->mountPoint have trailing slash
fsConfig = _config;
// make sure rootDir ends in '/', so that we can form a path by appending
// the rest..
if (rootDir[rootDir.length() - 1] != '/') rootDir.append(1, '/');
naming = fsConfig->nameCoding;
}
@ -277,6 +273,27 @@ string DirNode::rootDirectory() {
return string(rootDir, 0, rootDir.length() - 1);
}
bool DirNode::touchesMountpoint( const char *realPath ) const {
const string &mountPoint = fsConfig->opts->mountPoint;
// compare mountPoint up to the leading slash.
// examples:
// mountPoint = /home/user/Junk/experiment/
// realPath = /home/user/Junk/experiment
// realPath = /home/user/Junk/experiment/abc
const ssize_t len = mountPoint.length() - 1;
if (mountPoint.compare(0, len, realPath, len) == 0) {
// if next character is a NUL or a slash, then we're referencing our
// mount point:
// .../experiment => true
// .../experiment/... => true
// .../experiment2/abc => false
return realPath[len] == '\0' || realPath[len] == '/';
}
return false;
}
/**
* Encrypt a plain-text file path to the ciphertext path with the
* ciphertext root directory name prefixed.

View File

@ -86,6 +86,9 @@ class DirNode {
// return the path to the root directory
std::string rootDirectory();
// recursive lookup check
bool touchesMountpoint(const char *realPath) const;
// find files
shared_ptr<FileNode> lookupNode(const char *plaintextName,
const char *requestor);

View File

@ -69,6 +69,7 @@ enum ConfigMode { Config_Prompt, Config_Standard, Config_Paranoia };
*/
struct EncFS_Opts {
std::string rootDir;
std::string mountPoint; // where to make filesystem visible
bool createIfNotFound; // create filesystem if not found
bool idleTracking; // turn on idle monitoring of filesystem
bool mountOnDemand; // mounting on-demand

View File

@ -139,6 +139,14 @@ static int withFileNode(const char *opName, const char *path,
rAssert(fnode.get() != NULL);
rLog(Info, "%s %s", opName, fnode->cipherName());
// check that we're not recursing into the mount point itself
if (FSRoot->touchesMountpoint(fnode->cipherName())) {
rInfo("%s error: Tried to touch mountpoint: '%s'",
opName, fnode->cipherName());
return res; // still -EIO
}
res = op(fnode.get());
if (res < 0) rInfo("%s error: %s", opName, strerror(-res));

View File

@ -74,7 +74,6 @@ const int MaxFuseArgs = 32;
* derived from the arguments
*/
struct EncFS_Args {
string mountPoint; // where to make filesystem visible
bool isDaemon; // true == spawn in background, log to syslog
bool isThreaded; // true == threaded
bool isVerbose; // false == only enable warning/error messages
@ -373,8 +372,10 @@ static bool processArgs(int argc, char *argv[],
// we should have at least 2 arguments left over - the source directory and
// the mount point.
if (optind + 2 <= argc) {
// both rootDir and mountPoint are assumed to be slash terminated in the
// rest of the code.
out->opts->rootDir = slashTerminate(argv[optind++]);
out->mountPoint = argv[optind++];
out->opts->mountPoint = slashTerminate(argv[optind++]);
} else {
// no mount point specified
rWarning(_("Missing one or more arguments, aborting."));
@ -420,7 +421,7 @@ static bool processArgs(int argc, char *argv[],
}
// sanity check
if (out->isDaemon && (!isAbsolutePath(out->mountPoint.c_str()) ||
if (out->isDaemon && (!isAbsolutePath(out->opts->mountPoint.c_str()) ||
!isAbsolutePath(out->opts->rootDir.c_str()))) {
cerr <<
// xgroup(usage)
@ -431,7 +432,7 @@ static bool processArgs(int argc, char *argv[],
// the raw directory may not be a subdirectory of the mount point.
{
string testMountPoint = slashTerminate(out->mountPoint);
string testMountPoint = out->opts->mountPoint;
string testRootDir = out->opts->rootDir.substr(0, testMountPoint.length());
if (testMountPoint == testRootDir) {
@ -464,15 +465,15 @@ static bool processArgs(int argc, char *argv[],
rWarning(_("Unable to locate root directory, aborting."));
return false;
}
if (!isDirectory(out->mountPoint.c_str()) &&
!userAllowMkdir(out->opts->annotate ? 2 : 0, out->mountPoint.c_str(),
if (!isDirectory(out->opts->mountPoint.c_str()) &&
!userAllowMkdir(out->opts->annotate ? 2 : 0, out->opts->mountPoint.c_str(),
0700)) {
rWarning(_("Unable to locate mount point, aborting."));
return false;
}
// fill in mount path for fuse
out->fuseArgv[1] = out->mountPoint.c_str();
out->fuseArgv[1] = out->opts->mountPoint.c_str();
return true;
}
@ -767,7 +768,7 @@ static bool unmountFS(EncFS_Context *ctx) {
shared_ptr<EncFS_Args> arg = ctx->args;
if (arg->opts->mountOnDemand) {
rDebug("Detaching filesystem %s due to inactivity",
arg->mountPoint.c_str());
arg->opts->mountPoint.c_str());
ctx->setRoot(shared_ptr<DirNode>());
return false;
@ -775,8 +776,8 @@ static bool unmountFS(EncFS_Context *ctx) {
// Time to unmount!
// xgroup(diag)
rWarning(_("Unmounting filesystem %s due to inactivity"),
arg->mountPoint.c_str());
fuse_unmount(arg->mountPoint.c_str());
arg->opts->mountPoint.c_str());
fuse_unmount(arg->opts->mountPoint.c_str());
return true;
}
}