summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netfs/daemon/daemonVolume.cpp2
-rw-r--r--netfs/daemon/modeCheck.cpp12
-rw-r--r--netfs/daemon/modeCheck.h1
-rw-r--r--netfs/unittests/testCore.cpp30
4 files changed, 44 insertions, 1 deletions
diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp
index e4c65bd..5064b5b 100644
--- a/netfs/daemon/daemonVolume.cpp
+++ b/netfs/daemon/daemonVolume.cpp
@@ -161,7 +161,7 @@ VolumeServer::chmod(const NetFS::ReqEnv & re, const std::string & path, Ice::Int
ModeCheck mc(re, root, userLookup, groupLookup);
errno = 0;
boost::filesystem::path p(resolvePath(path));
- mc.AssertWrite(p);
+ mc.AssertWritePerms(p);
if (::chmod(p.c_str(), mode) != 0) {
throw NetFS::SystemError(errno);
}
diff --git a/netfs/daemon/modeCheck.cpp b/netfs/daemon/modeCheck.cpp
index dd1464c..df409bf 100644
--- a/netfs/daemon/modeCheck.cpp
+++ b/netfs/daemon/modeCheck.cpp
@@ -52,6 +52,18 @@ ModeCheck::AssertWrite(const boost::filesystem::path & p) const
}
}
+void
+ModeCheck::AssertWritePerms(const boost::filesystem::path & p) const
+{
+ if (p != root) {
+ AssertRead(p.parent_path());
+ }
+ auto s = lstat(p);
+ if (s.st_uid != myu && !WritableBy(s, myu, myg)) {
+ throw NetFS::SystemError(EACCES);
+ }
+}
+
struct stat
ModeCheck::lstat(const boost::filesystem::path & p)
{
diff --git a/netfs/daemon/modeCheck.h b/netfs/daemon/modeCheck.h
index 6c3ee2c..54a82e2 100644
--- a/netfs/daemon/modeCheck.h
+++ b/netfs/daemon/modeCheck.h
@@ -14,6 +14,7 @@ class ModeCheck {
void AssertRead(const boost::filesystem::path &) const;
void AssertWriteParent(const boost::filesystem::path &) const;
void AssertWrite(const boost::filesystem::path &) const;
+ void AssertWritePerms(const boost::filesystem::path &) const;
const uid_t myu;
const gid_t myg;
diff --git a/netfs/unittests/testCore.cpp b/netfs/unittests/testCore.cpp
index 8a0d38b..fb41f65 100644
--- a/netfs/unittests/testCore.cpp
+++ b/netfs/unittests/testCore.cpp
@@ -251,6 +251,36 @@ BOOST_AUTO_TEST_CASE( symlinks )
BOOST_REQUIRE_EQUAL(fuse->unlink("/test3"), -ENOENT);
}
+BOOST_AUTO_TEST_CASE( access )
+{
+ struct stat st;
+ memset(&st, 0, sizeof(st));
+ BOOST_REQUIRE_EQUAL(fuse->access("/", F_OK), 0);
+ BOOST_REQUIRE_EQUAL(fuse->access("/missing", F_OK), -ENOENT);
+ BOOST_REQUIRE_EQUAL(fuse->mkdir("/dir", 0700), 0);
+ BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0);
+ BOOST_REQUIRE_EQUAL(st.st_mode, 0700 | S_IFDIR);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", F_OK), 0);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", R_OK), 0);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", W_OK), 0);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", X_OK), 0);
+ BOOST_REQUIRE_EQUAL(fuse->chmod("/dir", 0000), 0);
+ BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0);
+ BOOST_REQUIRE_EQUAL(st.st_mode, 0000 | S_IFDIR);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", F_OK), 0);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", R_OK), -EACCES);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", W_OK), -EACCES);
+ BOOST_REQUIRE_EQUAL(fuse->access("/dir", X_OK), -EACCES);
+ BOOST_REQUIRE_EQUAL(fuse->chmod("/dir", 0500), 0);
+ BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0);
+ BOOST_REQUIRE_EQUAL(st.st_mode, 0500 | S_IFDIR);
+ BOOST_REQUIRE_EQUAL(fuse->rmdir("/dir"), -EACCES);
+ BOOST_REQUIRE_EQUAL(fuse->chmod("/dir", 0700), 0);
+ BOOST_REQUIRE_EQUAL(fuse->getattr("/dir", &st), 0);
+ BOOST_REQUIRE_EQUAL(st.st_mode, 0700 | S_IFDIR);
+ BOOST_REQUIRE_EQUAL(fuse->rmdir("/dir"), 0);
+}
+
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_CASE( testNoAuthNoPass )