summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netfs/daemon/daemonVolume.cpp9
-rw-r--r--netfs/unittests/testCore.cpp30
2 files changed, 37 insertions, 2 deletions
diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp
index 087eaf7..7ab8bd1 100644
--- a/netfs/daemon/daemonVolume.cpp
+++ b/netfs/daemon/daemonVolume.cpp
@@ -12,13 +12,14 @@
#include "lockHelpers.h"
#include "modeCheck.h"
#include <boost/filesystem/operations.hpp>
+#include <boost/algorithm/string/predicate.hpp>
#include <entCache.h>
#include "daemon.h"
extern std::map<Ice::Int, int> files;
VolumeServer::VolumeServer(const boost::filesystem::path & r, const EntCache<User> & u, const EntCache<Group> & g) :
- root(r),
+ root(boost::filesystem::canonical(r)),
userLookup(u),
groupLookup(g)
{
@@ -326,6 +327,10 @@ boost::filesystem::path
VolumeServer::resolvePath(const std::string & path) const
{
Lock(lock);
- return root / path;
+ auto p((root / path).normalize());
+ if (!boost::algorithm::starts_with(p.string(), root.string())) {
+ throw NetFS::SystemError(EPERM);
+ }
+ return p;
}
diff --git a/netfs/unittests/testCore.cpp b/netfs/unittests/testCore.cpp
index 27a5cf4..7e5136e 100644
--- a/netfs/unittests/testCore.cpp
+++ b/netfs/unittests/testCore.cpp
@@ -48,6 +48,36 @@ BOOST_AUTO_TEST_CASE ( clientInitialised )
BOOST_REQUIRE_EQUAL(0, fuse->statfs("/", &s));
}
+BOOST_AUTO_TEST_CASE( testSandboxing )
+{
+ // A previous (bad) run might create one or more of these:
+ boost::filesystem::remove(rootDir / "outside");
+ boost::filesystem::remove(rootDir / "sub" / "outside");
+ boost::filesystem::remove(rootDir / "sub");
+ struct fuse_file_info fi;
+ memset(&fi, 0, sizeof(fi));
+ BOOST_REQUIRE_EQUAL(fuse->create("../outside", 0666, &fi), -EPERM);
+ BOOST_REQUIRE(!boost::filesystem::exists(rootDir / "outside"));
+ BOOST_REQUIRE_EQUAL(fuse->create("/../outside", 0666, &fi), -EPERM);
+ BOOST_REQUIRE(!boost::filesystem::exists(rootDir / "outside"));
+ BOOST_REQUIRE_EQUAL(fuse->create("../sub/outside", 0666, &fi), -EPERM);
+ BOOST_REQUIRE(!boost::filesystem::exists(rootDir / "sub" / "outside"));
+ BOOST_REQUIRE_EQUAL(fuse->create("/../sub/outside", 0666, &fi), -EPERM);
+ BOOST_REQUIRE(!boost::filesystem::exists(rootDir / "sub" / "outside"));
+ BOOST_REQUIRE_EQUAL(fuse->create("../sub/../outside", 0666, &fi), -EPERM);
+ BOOST_REQUIRE(!boost::filesystem::exists(rootDir / "outside"));
+ BOOST_REQUIRE_EQUAL(fuse->create("/../sub/../outside", 0666, &fi), -EPERM);
+ BOOST_REQUIRE(!boost::filesystem::exists(rootDir / "outside"));
+ int fd = fuse->create("/inside", 0666, &fi);
+ BOOST_REQUIRE(fd >= 0);
+ fuse->release("/inside", &fi);
+ BOOST_REQUIRE(boost::filesystem::exists(rootDir / "testExport" / "inside"));
+ int fd2 = fuse->create("inside", 0666, &fi);
+ BOOST_REQUIRE(fd2 >= 0);
+ fuse->release("inside", &fi);
+ BOOST_REQUIRE(boost::filesystem::exists(rootDir / "testExport" / "inside"));
+}
+
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_CASE( testNoAuthNoPass )