Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perform checks to ensure that we're not descending into ourself. #125

Merged
merged 1 commit into from Nov 15, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 22 additions & 5 deletions encfs/DirNode.cpp
Expand Up @@ -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;
}

Expand All @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions encfs/DirNode.h
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions encfs/FileUtils.h
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions encfs/encfs.cpp
Expand Up @@ -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));
Expand Down
21 changes: 11 additions & 10 deletions encfs/main.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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."));
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -767,16 +768,16 @@ 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;
} else {
// 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;
}
}