svn commit: r347367 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs
Alan Somers
asomers at FreeBSD.org
Wed May 8 19:42:01 UTC 2019
Author: asomers
Date: Wed May 8 19:42:00 2019
New Revision: 347367
URL: https://svnweb.freebsd.org/changeset/base/347367
Log:
fusefs: allow non-owners to set timestamps to UTIME_NOW
utimensat should allow anybody with write access to set atime and mtime to
UTIME_NOW.
PR: 237181
Sponsored by: The FreeBSD Foundation
Modified:
projects/fuse2/sys/fs/fuse/fuse_vnops.c
projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc
Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_vnops.c Wed May 8 19:27:30 2019 (r347366)
+++ projects/fuse2/sys/fs/fuse/fuse_vnops.c Wed May 8 19:42:00 2019 (r347367)
@@ -1609,14 +1609,12 @@ fuse_vnop_setattr(struct vop_setattr_args *ap)
}
/* Don't set accmode. Permission to trunc is checked upstack */
}
- /*
- * TODO: for atime and mtime, only require VWRITE if UTIMENS_NULL is
- * set. PR 237181
- */
- if (vap->va_atime.tv_sec != VNOVAL)
- accmode |= VADMIN;
- if (vap->va_mtime.tv_sec != VNOVAL)
- accmode |= VADMIN;
+ if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
+ if (vap->va_vaflags & VA_UTIMES_NULL)
+ accmode |= VWRITE;
+ else
+ accmode |= VADMIN;
+ }
if (drop_suid) {
if (vap->va_mode != (mode_t)VNOVAL)
vap->va_mode &= ~(S_ISUID | S_ISGID);
Modified: projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc Wed May 8 19:27:30 2019 (r347366)
+++ projects/fuse2/tests/sys/fs/fusefs/default_permissions.cc Wed May 8 19:42:00 2019 (r347367)
@@ -141,6 +141,7 @@ class Lookup: public DefaultPermissions {};
class Open: public DefaultPermissions {};
class Setattr: public DefaultPermissions {};
class Unlink: public DefaultPermissions {};
+class Utimensat: public DefaultPermissions {};
class Write: public DefaultPermissions {};
/*
@@ -542,6 +543,60 @@ TEST_F(Deleteextattr, system)
ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo"));
ASSERT_EQ(EPERM, errno);
+}
+
+/* Anybody with write permission can set both timestamps to UTIME_NOW */
+TEST_F(Utimensat, utime_now)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ const uint64_t ino = 42;
+ /* Write permissions for everybody */
+ const mode_t mode = 0666;
+ uid_t owner = 0;
+ const timespec times[2] = {
+ {.tv_sec = 0, .tv_nsec = UTIME_NOW},
+ {.tv_sec = 0, .tv_nsec = UTIME_NOW},
+ };
+
+ expect_getattr(1, S_IFDIR | 0755, UINT64_MAX, 1);
+ expect_lookup(RELPATH, ino, S_IFREG | mode, UINT64_MAX, owner);
+ EXPECT_CALL(*m_mock, process(
+ ResultOf([](auto in) {
+ return (in->header.opcode == FUSE_SETATTR &&
+ in->header.nodeid == ino &&
+ in->body.setattr.valid & FATTR_ATIME &&
+ in->body.setattr.valid & FATTR_MTIME);
+ }, Eq(true)),
+ _)
+ ).WillOnce(Invoke(ReturnImmediate([](auto in __unused, auto out) {
+ SET_OUT_HEADER_LEN(out, attr);
+ out->body.attr.attr.mode = S_IFREG | mode;
+ })));
+
+ ASSERT_EQ(0, utimensat(AT_FDCWD, FULLPATH, ×[0], 0))
+ << strerror(errno);
+}
+
+/* Anybody can set both timestamps to UTIME_OMIT */
+TEST_F(Utimensat, utime_omit)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ const uint64_t ino = 42;
+ /* Write permissions for no one */
+ const mode_t mode = 0444;
+ uid_t owner = 0;
+ const timespec times[2] = {
+ {.tv_sec = 0, .tv_nsec = UTIME_OMIT},
+ {.tv_sec = 0, .tv_nsec = UTIME_OMIT},
+ };
+
+ expect_getattr(1, S_IFDIR | 0755, UINT64_MAX, 1);
+ expect_lookup(RELPATH, ino, S_IFREG | mode, UINT64_MAX, owner);
+
+ ASSERT_EQ(0, utimensat(AT_FDCWD, FULLPATH, ×[0], 0))
+ << strerror(errno);
}
/* Deleting user attributes merely requires WRITE privilege */
More information about the svn-src-projects
mailing list