fuse permission fixes
This commit is contained in:
parent
bd25904371
commit
841d57cf13
@ -170,6 +170,9 @@ renterd
|
||||
richtext
|
||||
rocksdb_library
|
||||
rpcrt4
|
||||
s_igid
|
||||
s_isvtx
|
||||
s_iuid
|
||||
sddl_revision_1
|
||||
secp256k1
|
||||
secur32
|
||||
@ -218,4 +221,4 @@ wsign-conversion
|
||||
wunused
|
||||
wuseless
|
||||
wxwidgets_version
|
||||
xattr
|
||||
xattr
|
@ -67,6 +67,11 @@ auto fuse_drive::chmod_impl(std::string api_path, mode_t mode,
|
||||
auto fuse_drive::chmod_impl(std::string api_path, mode_t mode) -> api_error {
|
||||
#endif // FUSE_USE_VERSION >= 30
|
||||
return check_and_perform(api_path, X_OK, [&](api_meta_map &) -> api_error {
|
||||
if ((mode & (S_IGID | S_IUID | S_ISVTX) != 0) &&
|
||||
(get_effective_uid() != 0)) {
|
||||
return api_error::permission_denied;
|
||||
}
|
||||
|
||||
return provider_.set_item_meta(api_path, META_MODE, std::to_string(mode));
|
||||
});
|
||||
}
|
||||
@ -86,23 +91,24 @@ auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||
if (get_effective_uid() != 0) {
|
||||
return api_error::permission_denied;
|
||||
}
|
||||
|
||||
meta[META_UID] = std::to_string(uid);
|
||||
}
|
||||
|
||||
if (gid != static_cast<gid_t>(-1)) {
|
||||
if (get_effective_uid() != 0) {
|
||||
if (not utils::is_uid_member_of_group(get_effective_uid(), gid)) {
|
||||
return api_error::permission_denied;
|
||||
}
|
||||
if (get_effective_uid() != 0 &&
|
||||
not utils::is_uid_member_of_group(get_effective_uid(), gid)) {
|
||||
return api_error::permission_denied;
|
||||
}
|
||||
|
||||
meta[META_GID] = std::to_string(gid);
|
||||
}
|
||||
|
||||
if (not meta.empty()) {
|
||||
return provider_.set_item_meta(api_path, meta);
|
||||
if (meta.empty()) {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
return provider_.set_item_meta(api_path, meta);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -32,16 +32,22 @@
|
||||
#include "providers/encrypt/encrypt_provider.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
#include "providers/sia/sia_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/event_capture.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
#if !defined(ACCESSPERMS)
|
||||
#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO) /* 0777 */
|
||||
#endif
|
||||
|
||||
namespace repertory {
|
||||
inline constexpr const auto SLEEP_SECONDS{1.5s};
|
||||
namespace {
|
||||
std::atomic<std::size_t> idx{0U};
|
||||
constexpr const auto SLEEP_SECONDS{1.5s};
|
||||
} // namespace
|
||||
|
||||
namespace repertory {
|
||||
template <typename provider_t> class fuse_test : public ::testing::Test {
|
||||
public:
|
||||
static std::string cfg_directory;
|
||||
@ -147,7 +153,10 @@ protected:
|
||||
|
||||
public:
|
||||
static auto create_file_and_test(std::string name) -> std::string {
|
||||
auto file_path = utils::path::combine(mount_location, {name});
|
||||
auto file_path =
|
||||
utils::path::combine(mount_location, {
|
||||
name + std::to_string(++idx),
|
||||
});
|
||||
|
||||
auto fd =
|
||||
open(file_path.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
@ -166,6 +175,19 @@ public:
|
||||
return file_path;
|
||||
}
|
||||
|
||||
static auto create_root_file(std::string name) -> std::string {
|
||||
auto file_path = create_file_and_test(name);
|
||||
|
||||
auto api_path =
|
||||
utils::path::create_api_path(utils::path::strip_to_filename(file_path));
|
||||
provider->set_item_meta(api_path, {
|
||||
{META_UID, "0"},
|
||||
{META_GID, "0"},
|
||||
});
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
||||
static void execute_mount(auto &&drive_args) {
|
||||
auto mount_cmd = "./repertory -dd \"" + config->get_data_directory() +
|
||||
"\"" + " " + utils::string::join(drive_args, ' ');
|
||||
@ -200,6 +222,18 @@ public:
|
||||
EXPECT_FALSE(utils::file::directory(file_path).exists());
|
||||
EXPECT_FALSE(utils::file::file(file_path).exists());
|
||||
}
|
||||
|
||||
static void unlink_root_file(const std::string &file_path) {
|
||||
auto api_path =
|
||||
utils::path::create_api_path(utils::path::strip_to_filename(file_path));
|
||||
|
||||
provider->set_item_meta(api_path, {
|
||||
{META_UID, std::to_string(getuid())},
|
||||
{META_GID, std::to_string(getgid())},
|
||||
});
|
||||
|
||||
unlink_file_and_test(file_path);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename provider_t>
|
||||
|
@ -19,22 +19,10 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#if 0
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include "fixtures/fuse_fixture.hpp"
|
||||
|
||||
// #include "app_config.hpp"
|
||||
// #include "comm/curl/curl_comm.hpp"
|
||||
// #include "drives/fuse/fuse_drive.hpp"
|
||||
// #include "platform/platform.hpp"
|
||||
// #include "providers/s3/s3_provider.hpp"
|
||||
// #include "providers/sia/sia_provider.hpp"
|
||||
// #include "types/repertory.hpp"
|
||||
// #include "utils/event_capture.hpp"
|
||||
// #include "utils/file_utils.hpp"
|
||||
// #include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
// static void rmdir_and_test(const std::string &directory_path) {
|
||||
// std::cout << __FUNCTION__ << std::endl;
|
||||
@ -529,36 +517,119 @@ namespace repertory {
|
||||
|
||||
TYPED_TEST_CASE(fuse_test, fuse_provider_types);
|
||||
|
||||
TYPED_TEST(fuse_test, chmod) {
|
||||
TYPED_TEST(fuse_test, can_chmod_if_owner) {
|
||||
auto file_path = this->create_file_and_test("chmod_test");
|
||||
EXPECT_EQ(0, chmod(file_path.c_str(), S_IRUSR | S_IWUSR));
|
||||
std::this_thread::sleep_for(SLEEP_SECONDS);
|
||||
|
||||
struct stat64 unix_st {};
|
||||
struct stat64 unix_st{};
|
||||
stat64(file_path.c_str(), &unix_st);
|
||||
EXPECT_EQ(static_cast<std::uint32_t>(S_IRUSR | S_IWUSR),
|
||||
ACCESSPERMS & unix_st.st_mode);
|
||||
|
||||
this->unlink_file_and_test(file_path);
|
||||
}
|
||||
|
||||
TYPED_TEST(fuse_test, chown) {
|
||||
TYPED_TEST(fuse_test, can_not_chmod_if_not_owner) {
|
||||
auto file_path = this->create_root_file("chmod_test");
|
||||
EXPECT_EQ(-1, chmod(file_path.c_str(), S_IRUSR | S_IWUSR));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
|
||||
this->unlink_root_file(file_path);
|
||||
}
|
||||
|
||||
TYPED_TEST(fuse_test, can_not_chmod_setgid_if_not_root) {
|
||||
auto file_path = this->create_file_and_test("chown_test");
|
||||
EXPECT_EQ(0, chown(file_path.c_str(), static_cast<uid_t>(-1), 0));
|
||||
EXPECT_EQ(-1, chmod(file_path.c_str(), S_IRUSR | S_IWUSR | S_IGID));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
|
||||
this->unlink_file_and_test(file_path);
|
||||
}
|
||||
|
||||
TYPED_TEST(fuse_test, can_not_chmod_setuid_if_not_root) {
|
||||
auto file_path = this->create_file_and_test("chown_test");
|
||||
EXPECT_EQ(-1, chmod(file_path.c_str(), S_IRUSR | S_IWUSR | S_IUID));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
|
||||
this->unlink_file_and_test(file_path);
|
||||
}
|
||||
|
||||
TYPED_TEST(fuse_test, can_not_chmod_set_sticky_if_not_root) {
|
||||
auto file_path = this->create_file_and_test("chown_test");
|
||||
EXPECT_EQ(-1, chmod(file_path.c_str(), S_IRUSR | S_IWUSR | S_ISVTX));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
|
||||
this->unlink_file_and_test(file_path);
|
||||
}
|
||||
|
||||
TYPED_TEST(fuse_test, can_chown_group_if_owner_and_a_member_of_the_group) {
|
||||
auto file_path = this->create_file_and_test("chown_test");
|
||||
|
||||
struct stat64 unix_st{};
|
||||
EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st));
|
||||
|
||||
EXPECT_EQ(0, chown(file_path.c_str(), static_cast<uid_t>(-1), getgid()));
|
||||
std::this_thread::sleep_for(SLEEP_SECONDS);
|
||||
|
||||
struct stat64 unix_st {};
|
||||
stat64(file_path.c_str(), &unix_st);
|
||||
EXPECT_EQ(0U, unix_st.st_gid);
|
||||
struct stat64 unix_st2{};
|
||||
stat64(file_path.c_str(), &unix_st2);
|
||||
EXPECT_EQ(getgid(), unix_st2.st_gid);
|
||||
EXPECT_EQ(unix_st.st_uid, unix_st2.st_uid);
|
||||
|
||||
EXPECT_EQ(0, chown(file_path.c_str(), 0, static_cast<gid_t>(-1)));
|
||||
std::this_thread::sleep_for(SLEEP_SECONDS);
|
||||
this->unlink_file_and_test(file_path);
|
||||
}
|
||||
|
||||
stat64(file_path.c_str(), &unix_st);
|
||||
EXPECT_EQ(0U, unix_st.st_gid);
|
||||
TYPED_TEST(fuse_test,
|
||||
can_not_chown_group_if_owner_but_not_a_member_of_the_group) {
|
||||
auto file_path = this->create_file_and_test("chown_test");
|
||||
|
||||
struct stat64 unix_st{};
|
||||
EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st));
|
||||
|
||||
EXPECT_EQ(-1, chown(file_path.c_str(), static_cast<uid_t>(-1), 0));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
|
||||
struct stat64 unix_st2{};
|
||||
stat64(file_path.c_str(), &unix_st2);
|
||||
EXPECT_EQ(unix_st.st_gid, unix_st2.st_gid);
|
||||
EXPECT_EQ(unix_st.st_uid, unix_st2.st_uid);
|
||||
|
||||
this->unlink_file_and_test(file_path);
|
||||
}
|
||||
|
||||
TYPED_TEST(fuse_test, can_not_chown_group_if_not_the_owner) {
|
||||
auto file_path = this->create_root_file("chown_test");
|
||||
|
||||
struct stat64 unix_st{};
|
||||
EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st));
|
||||
|
||||
EXPECT_EQ(-1, chown(file_path.c_str(), static_cast<uid_t>(-1), getgid()));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
|
||||
struct stat64 unix_st2{};
|
||||
stat64(file_path.c_str(), &unix_st2);
|
||||
EXPECT_EQ(unix_st.st_gid, unix_st2.st_gid);
|
||||
EXPECT_EQ(unix_st.st_uid, unix_st2.st_uid);
|
||||
|
||||
this->unlink_root_file(file_path);
|
||||
}
|
||||
|
||||
TYPED_TEST(fuse_test, can_not_chown_user_if_not_root) {
|
||||
auto file_path = this->create_file_and_test("chown_test");
|
||||
|
||||
struct stat64 unix_st{};
|
||||
EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st));
|
||||
|
||||
EXPECT_EQ(-1, chown(file_path.c_str(), 0, static_cast<gid_t>(-1)));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
|
||||
struct stat64 unix_st2{};
|
||||
stat64(file_path.c_str(), &unix_st2);
|
||||
EXPECT_EQ(unix_st.st_gid, unix_st2.st_gid);
|
||||
EXPECT_EQ(unix_st.st_uid, unix_st2.st_uid);
|
||||
|
||||
this->unlink_file_and_test(file_path);
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
#endif // !defined(_WIN32)
|
||||
#endif // 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user