svn commit: r291936 - head/sys/ufs/ufs

Bruce Evans brde at optusnet.com.au
Mon Dec 7 14:57:57 UTC 2015


On Mon, 7 Dec 2015, Konstantin Belousov wrote:

> Log:
>  Update ctime when atime or birthtime are updated.
>
>  Cleanup setting of ctime/mtime/birthtime: do not set IN_ACCESS or
>  IN_UPDATE, then clear them with ufs_itimes(), making transient
>  (possibly inconsistent) change to the times, and then copy
>  user-supplied times into the inode.  Instead, directly clear IN_ACCESS
>  or IN_UPDATE when user supplied the time, and copy the value into the
>  inode.
>
>  Minor inconsistency left is that the inode ctime is updated even when
>  birthtime update attempt is performed on a UFS1 volume.
>
>  Submitted by:	bde
>  MFC after:	2 weeks

Thanks.

I forgot to remind yo to make the same change in other file systems.
Especially ext2fs.  msdosfs already has as much as possible of this.

POSIX generally requires even null changes of attributes to update the
ctime, so it is not wrong to always update the ctime when the only change
is for an unsupported birthtime.   This also happens for other file systems
that don't support birthtimes.  Other file systems might also not support
other timestamps.  msdosfs doesn't support ctimes so it doesn't need to
worry about setting them for null and ignored changes to other timestamps.
It ignores attempts to set unsupported times, like ffs does for birthtimes.
Some versions of msdosfs support birthtimes, but msdosfs_setattr() doesn't
support them.

But POSIX also requires omitted changes of attributes to update the ctime.
For timestamp attributes, it even requires the security hole of updating
the ctime when changing the other times fails (perhaps due to no permission
to change them), and the nonsense of updating the ctime when the file
doesn't exist.  The security hole and the nonsense are because POSIX is
missing "successful" in the usual wording "Upon successful completion"
in one place.

The cases with omitted changes occur mainly for utimensat().  UTIME_OMIT
for both times gives 2 omitted changes and not 2 null changes.  Clearly
the ctime should not be changed when all changes are omitted.  But
POSIX requires utimensat() to mark the ctime for update on all completions.
This gives the security hole but not the nonsense of acting on a nonexistent
file in a way in a less unintentional way than the missing "successful".
POSIX requires not doing the permissions tests for omitted changes.  So
2 omitted changes normally result in success for files that would fail
the permissions tests for non-omitted changes.  Then the correct
"Upon successful completion" wording requires marking the ctime.

Some other syscalls like chown() provide another way of omitting
changes: Uid (uid_t)-1 means to use the current uid of the file, etc.
This is closer to a null change than an omitted change.

FressBSD has a different set of bugs in this area.  For utimes() and also
for utimensat(), it has the undocumented behaviour of turning times
with tv_sec == -1 into the equivalent of UTIME_OMIT, the standard
utimes() doesn't have such a feature and standard utimensat() is only
supposed to have this feature by magic values in tv_nsec.  Similarly for
chown().  For file times, this is the accidental result of an
implementation detail.  For chown(), it is more intentional.  POSIX
chown() has smaller wording bugs and doesn't require the security hole.

Most appplications do extra work to avoid null changes.  It is unclear
if this is allowed.  Maybe chown -R root:wheel / is require to update
the ctime for all files, not just the ones it makes non-null changes to.
This is negatively useful, but not disallowed.

Bruce


More information about the svn-src-head mailing list