DF-2629 / fix.diff
diff --git a/sys/vfs/hammer2/hammer2_vnops.c b/sys/vfs/hammer2/hammer2_vnops.c index 1111111..3333333 100644 @@ -558,6 +558,28 @@ } } + /* + * Timestamp updates require the same authority UFS enforces in + * ufs_setattr() (sys/vfs/ufs/ufs_vnops.c): the file owner, a + * privileged caller, or (VA_UTIMES_NULL set AND write access). + * The syscall layer only pre-filters owner-or-write-access via + * nlookup (NLC_OWN|NLC_WRITE in kern_utimensat), which lets any + * write-permitted non-owner through to VOP_SETATTR with explicit + * timestamps - hammer2 must reject those itself or mtime can be + * forged. + */ + if (vap->va_mtime.tv_sec != VNOVAL || + vap->va_atime.tv_sec != VNOVAL) { + uid_t cur_uid = hammer2_to_unix_xid(&ip->meta.uid); + + if (ap->a_cred->cr_uid != cur_uid && + (error = caps_priv_check(ap->a_cred, + SYSCAP_NOVFS_SETATTR)) != 0 && + ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || + (error = VOP_EACCESS(vp, VWRITE, ap->a_cred)) != 0)) { + goto done; + } + } if (vap->va_mtime.tv_sec != VNOVAL) { hammer2_inode_modify(ip); ip->meta.mtime = hammer2_timespec_to_time(&vap->va_mtime); |