From 140bb4927aff197ccec5174d00d7442887db1245 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 5 Apr 2019 15:33:43 +0000 Subject: [PATCH] fusefs: correctly return EROFS from VOP_ACCESS Sponsored by: The FreeBSD Foundation --- sys/fs/fuse/fuse_internal.c | 2 +- tests/sys/fs/fusefs/access.cc | 21 +++++++++++++++++++++ tests/sys/fs/fusefs/mockfs.cc | 6 +++++- tests/sys/fs/fusefs/mockfs.hh | 2 +- tests/sys/fs/fusefs/utils.cc | 2 +- tests/sys/fs/fusefs/utils.hh | 4 +++- 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/sys/fs/fuse/fuse_internal.c b/sys/fs/fuse/fuse_internal.c index 52f0d80e335d..7c548b44f6d3 100644 --- a/sys/fs/fuse/fuse_internal.c +++ b/sys/fs/fuse/fuse_internal.c @@ -137,7 +137,7 @@ fuse_internal_access(struct vnode *vp, dataflags = data->dataflags; if ((mode & VWRITE) && vfs_isrdonly(mp)) { - return EACCES; + return EROFS; } /* Unless explicitly permitted, deny everyone except the fs owner. */ if (vnode_isvroot(vp) && !(facp->facc_flags & FACCESS_NOCHECKSPY)) { diff --git a/tests/sys/fs/fusefs/access.cc b/tests/sys/fs/fusefs/access.cc index 016d9bcd8d8d..e36b0005bcda 100644 --- a/tests/sys/fs/fusefs/access.cc +++ b/tests/sys/fs/fusefs/access.cc @@ -46,6 +46,14 @@ void expect_lookup(const char *relpath, uint64_t ino) } }; +class RofsAccess: public Access { +public: +virtual void SetUp() { + m_ro = true; + Access::SetUp(); +} +}; + /* The error case of FUSE_ACCESS. */ /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236291 */ TEST_F(Access, DISABLED_eaccess) @@ -83,6 +91,19 @@ TEST_F(Access, DISABLED_enosys) ASSERT_EQ(0, access(FULLPATH, access_mode)) << strerror(errno); } +TEST_F(RofsAccess, erofs) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + uint64_t ino = 42; + mode_t access_mode = W_OK; + + expect_lookup(RELPATH, ino); + + ASSERT_NE(0, access(FULLPATH, access_mode)); + ASSERT_EQ(EROFS, errno); +} + /* The successful case of FUSE_ACCESS. */ /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236291 */ TEST_F(Access, DISABLED_ok) diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc index 5517ecc4f473..ec2c9b3a13c8 100644 --- a/tests/sys/fs/fusefs/mockfs.cc +++ b/tests/sys/fs/fusefs/mockfs.cc @@ -258,7 +258,7 @@ void debug_fuseop(const mockfs_buf_in *in) } MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions, - bool push_symlinks_in, uint32_t flags) + bool push_symlinks_in, bool ro, uint32_t flags) { struct iovec *iov = NULL; int iovlen = 0; @@ -307,6 +307,10 @@ MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions, build_iovec(&iov, &iovlen, "push_symlinks_in", __DECONST(void*, &trueval), sizeof(bool)); } + if (ro) { + build_iovec(&iov, &iovlen, "ro", + __DECONST(void*, &trueval), sizeof(bool)); + } if (nmount(iov, iovlen, 0)) throw(std::system_error(errno, std::system_category(), "Couldn't mount filesystem")); diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh index ac4c9a030e3b..52121f92331b 100644 --- a/tests/sys/fs/fusefs/mockfs.hh +++ b/tests/sys/fs/fusefs/mockfs.hh @@ -216,7 +216,7 @@ class MockFS { /* Create a new mockfs and mount it to a tempdir */ MockFS(int max_readahead, bool allow_other, - bool default_permissions, bool push_symlinks_in, + bool default_permissions, bool push_symlinks_in, bool ro, uint32_t flags); virtual ~MockFS(); diff --git a/tests/sys/fs/fusefs/utils.cc b/tests/sys/fs/fusefs/utils.cc index e00b9d3c148b..ec7374bf34e7 100644 --- a/tests/sys/fs/fusefs/utils.cc +++ b/tests/sys/fs/fusefs/utils.cc @@ -94,7 +94,7 @@ void FuseTest::SetUp() { try { m_mock = new MockFS(m_maxreadahead, m_allow_other, - m_default_permissions, m_push_symlinks_in, + m_default_permissions, m_push_symlinks_in, m_ro, m_init_flags); } catch (std::system_error err) { FAIL() << err.what(); diff --git a/tests/sys/fs/fusefs/utils.hh b/tests/sys/fs/fusefs/utils.hh index 4022be7da302..b9114ab16180 100644 --- a/tests/sys/fs/fusefs/utils.hh +++ b/tests/sys/fs/fusefs/utils.hh @@ -44,6 +44,7 @@ class FuseTest : public ::testing::Test { bool m_allow_other; bool m_default_permissions; bool m_push_symlinks_in; + bool m_ro; MockFS *m_mock = NULL; const static uint64_t FH = 0xdeadbeef1a7ebabe; @@ -59,7 +60,8 @@ class FuseTest : public ::testing::Test { m_init_flags(0), m_allow_other(false), m_default_permissions(false), - m_push_symlinks_in(false) + m_push_symlinks_in(false), + m_ro(false) {} virtual void SetUp();