diff options
-rw-r--r-- | netfs/daemon/daemonVolume.cpp | 9 | ||||
-rw-r--r-- | netfs/unittests/testCore.cpp | 30 |
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 ) |