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 )  | 
