fusefs: correctly return EROFS from VOP_ACCESS

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Alan Somers 2019-04-05 15:33:43 +00:00
parent 46c37cd0d7
commit 140bb4927a
6 changed files with 32 additions and 5 deletions

View File

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

View File

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

View File

@ -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"));

View File

@ -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();

View File

@ -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();

View File

@ -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();