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); Lock _lock(mutex);
ctx = _ctx; ctx = _ctx;
rootDir = sourceDir; rootDir = sourceDir; // .. and fsConfig->opts->mountPoint have trailing slash
fsConfig = _config; 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; naming = fsConfig->nameCoding;
} }
@ -277,6 +273,27 @@ string DirNode::rootDirectory() {
return string(rootDir, 0, rootDir.length() - 1); 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 * Encrypt a plain-text file path to the ciphertext path with the
* ciphertext root directory name prefixed. * ciphertext root directory name prefixed.

View File

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

View File

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

View File

@ -139,6 +139,14 @@ static int withFileNode(const char *opName, const char *path,
rAssert(fnode.get() != NULL); rAssert(fnode.get() != NULL);
rLog(Info, "%s %s", opName, fnode->cipherName()); 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()); res = op(fnode.get());
if (res < 0) rInfo("%s error: %s", opName, strerror(-res)); if (res < 0) rInfo("%s error: %s", opName, strerror(-res));

View File

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