#497514 coreutils: chmod, chown, and chgrp change ctime even when no change was necessary

Package:
coreutils
Source:
coreutils
Description:
GNU core utilities
Submitter:
Erik Rossen
Date:
2022-06-21 14:27:02 UTC
Severity:
wishlist
#497514#5
Date:
2008-09-02 09:30:46 UTC
From:
To:
It would be nice if chmod (and chown and chgrp) only made changes to
inodes when necessary so as not to change the ctime of files.

I like to use the integrit file integrity-checking program which scans
for changes to mtime and ctime.  I also occasionally set up "fix-perms"
cronjobs that scan directories recursively and fix any mis-configured of
permissions/ownerships.  The problem is that "chmod -R" and company
change the ctimes of all files, not just those that need to be fixed.
This causes excessively long (and useless) file integrity reports.

I could use cfengine to do the same job, but chmod is sometimes much
more convenient.

I have tested Busybox chmod and it suffers from the same behavior.

If unconditionally resetting the ctime of inodes is normal POSIX
behavior for chmod, then this function should be implemented as a option
flag.  If not, can the authors make "change-only-if-necessary" the
default behavior of chmod and company?

Thanks.

#497514#10
Date:
2008-09-02 12:19:38 UTC
From:
To:
I'm fairly certain there have also been complaints about these utilities
not resetting the inode even when not necessary. I'd suggest using them
in conjunction with find(1) if you only want to modify files that don't
match a particular setting.

Mike Stone

#497514#15
Date:
2008-09-02 13:50:16 UTC
From:
To:
That is certainly possible, if that is normal POSIX behavior.

Yup.

But it would be so much more elegant if chmod just Did The Right Thing.

Can I ask you to pass along this wishlist item to upstream and maybe ask
them why ctime must be modified even when the permissions are not?  I
would really like to know why.

#497514#20
Date:
2008-09-02 14:48:30 UTC
From:
To:
It's certainly arguable whether adding another non-standard flag is the
Right Thing when it's fairly trivial to get the result in a more
portable fashion using find(1).

Upstream monitors the debian bug logs and will presumably chime in if
interested. I vaguely recall that people want these utilities to act
even if not strictly necessary because of possible side effects for
extended attributes.

Mike Stone

#497514#25
Date:
2008-09-02 18:06:51 UTC
From:
To:
Erik Rossen <rossen@rossen.ch> wrote:

Good idea.
At least for chmod, it is not only possible, but the optimization
would be essentially free, since chmod already has the required stat data.

AFAICS POSIX
(http://www.opengroup.org/onlinepubs/007908775/xsh/chmod.html)
allows the behavior you propose.  That same feature was even
requested a few years ago, but no one implemented it.

A patch would be welcome.
If you're not interested, let me know in any case and
I'll add it to the TODO list.

If you are interested in writing the patch,
please follow the guidelines outlined here:
http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=blob;f=HACKING;hb=HEAD

For chgrp (probably chown, too, at least in some cases), it's not
as obvious, since the current implementation does not stat files
before changing permissions.  So, to do what you want would involve
adding a stat call per file to get owner/group in order to avoid(maybe)
the offending ownership-changing syscall.  That would not be an
improvement.

#497514#30
Date:
2008-09-02 18:56:43 UTC
From:
To:
Yeah, I thought it was a good idea too.

Thanks for the lead - I had no idea where to go looking for POSIX specs.
But you got the wrong URL.  The URL above refers to chmod() the
function.  What we needed was chmod the utility.  Here it is:

http://www.opengroup.org/onlinepubs/007908799/xcu/chmod.html

And, if one wants to be REALLY pedantic, it looks like the file node is
supposed to be changed each time.  For example, here is an extract:

	+
	    If perm is not specified, the + operation will not change
	    the file mode bits. If who is not specified, the file mode
	    bits represented by perm for the owner, group and other
	    permissions, except for those with corresponding bits in the
	    file mode creation mask of the invoking process, will be
	    set. Otherwise, the file mode bits represented by the
	    specified who and perm values will be set.

Here it says that the bits will be set.  Unfortunately, they do not say
something like "set unless already set".  If the feature is to added, it
will be a non-standard option.

I totally agree.

I think I will let you add it to the TODO list. :-)

As far as speed is concerned, you are right that an extra stat() would
usually not improve matters.  (Would it be an enormous penalty?  I doubt
it.)  But users of file integrity checking systems like myself will be
grateful for the change of behavior.

#497514#35
Date:
2008-09-02 20:30:20 UTC
From:
To:
Erik Rossen wrote:

You would be surprised how much performance can change when adding
extra stat calls.  Many filesystems such as networked filesystems are
extremely latency bound and those kinds of changes have a strong
negative impact upon them.

Bob

#497514#40
Date:
2008-09-02 20:57:28 UTC
From:
To:
OK.  But I still wonder how expensive are the extra stat() calls that
would be spent compared to the extra chown() calls that could be saved
by checking first to see if a chown() was even necessary?

#497514#45
Date:
2008-09-03 14:05:46 UTC
From:
To:
I asked the people on the mailing list of our local LUG to test if chmod
changes ctime on non-GNU systems even when there is no difference beteen
the mode before and after the chmod.  From these few data, the trend
seems to be that ctime gets changed.

Here are the results thus far (identified by "uname -a"):


systems that change ctime:
--------------------------

AIX XXXXXXXX 3 4 000650834C00
SunOS XXXXXXXX 5.8 Generic_108528-29 sun4u sparc SUNW,UltraSPARC-IIi-cEngine
OpenBSD XXXXXXXX 4.1 GENERIC#187 i386


systems that do not change ctime:
---------------------------------

FreeBSD XXXXXXXX 7.0-RELEASE FreeBSD 7.0-RELEASE #0: Sun Feb 24 19:59:52 UTC 2008 root@logan.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC i386

#497514#50
Date:
2008-09-04 09:01:51 UTC
From:
To:
Hi,

*IF* POSIX or general use mandates that chmod(2) should not change
ctime if no change really occurs, this should be fixed in the
Linux kernel itself.

Fixing it in user space in the chmod(1) utility is wrong, because it
could introduce user-space race conditions.

For example:
   timestamp 1: perm is 0500
   timestamp 2: perm is 0700
   timestamp 3: perm is 0500

we would expect c_time to be timestamp 3 at the end of this flow.

Now imagine that you have two processes. Process one wants to set
perm to 0500, process 2 to 0700.  Imagine it works as follows:

   process 1                      process 2
   stats file, gets perm 500
                                  stats files, get perm 0500
                                  set permissions to 0700, ctime changes


   set perm, no real change,
   so don't do anything

WRONG! permission is 0700!

(one could argue that the overall result is undefined if the two
processes are scheduled in parallel anyway; however there seem to be
something wrong in the user-space semantic here anyway)

(in general, any "I check manually, then I set" method is wrong,
 unless it is done atomically, which is not the case for user space
 and can only be guaranteed with kernel locks with currently used
 Linux kernels)

#497514#55
Date:
2008-09-04 11:36:54 UTC
From:
To:
Marc SCHAEFER <schaefer@alphanet.ch> wrote:

Neither mandates that.

#497514#60
Date:
2008-09-11 17:56:34 UTC
From:
To:
Erik Rossen <rossen@rossen.ch> writes:

As I read the spec, chown and chgrp are explicitly required to make
the equivalent of a chown() call, which in turn is required to change
the ctime.  However, chmod is not required to make the equivalent of a
chmod() call, and there is no requirement in the 'chmod' spec that it
change the ctime.  So POSIX allows the optimization for the 'chmod'
command, but not for the 'chown' and 'chgrp' commands.

#497514#65
Date:
2008-09-12 03:20:21 UTC
From:
To:
According to Paul Eggert on 9/11/2008 11:56 AM:

On the other hand, the POSIX spec for chmod(1) mentions that it is
implementation defined on how it affects alternate access control.  I have
come to expect on many systems that support ACLs, that 'chmod 755' on a
file with rwxr-xr-x+ permissions will remove the ACLs.  In other words,
optimizing away the chmod(2) call because it compares equal to the stat
information would break this side-effect of clearing ACLs.

#497514#70
Date:
2008-09-12 19:51:04 UTC
From:
To:
Eric Blake <ebb9@byu.net> wrote:

That sounds like a good reason to retain the behavior you've come to
value, even if it's not guaranteed or portable, but only via a new
option.  Then we can still change the default to be more efficient.

#497514#75
Date:
2008-09-12 20:05:09 UTC
From:
To:
Why on earth would we want to? Some people obviously like the current
behavior, and depend on the side effects, the desired behavior is easy
to get with existing tools, and adding a new option seems like something
that shouldn't be done without a very good reason. This seems like
optimization for the sake of optimization. (And it would make chmod
inconsistent with chown and chgrp.)

Mike Stone

#497514#80
Date:
2008-09-13 07:50:35 UTC
From:
To:
Michael Stone <mstone@debian.org> wrote:

I don't feel very strongly one way or the other,
since I don't plan to do the work.

Realize that afaik no one is working on this.
I merely added the item to the TODO list, and we
know from experience that that's no guarantee it'll be done.

#497514#85
Date:
2008-09-15 09:22:41 UTC
From:
To:
It seems that the FreeBSD people think that making a change to the
filesystem only when necessary is The Right Thing.  But I guess that
argument carries no weight in GNU. ;-)
three options for fixing file permissions without disturbing the file
system too much:

1.  find + chmod : classic but ugly

2.  cfengine : Does The Right Thing, but difficult to do as a one-liner
unless you are already using cfengine for other stuff

3.  setfacl -R : nice.  Does The Right Thing as a fairly simple one-liner

setfacl is kind of interesting.  Even if the filesystem is mounted
without extended ACLs enabled, it works for setting the POSIX ACLs and
it Does The Right Thing.  For example, I can do

	setfacl -R -m u::rwX,g::rwX,o:rX shares/

to fix every file and directory in "shares" to be readable, and writable
only by the owner and group of shares.  And if I run the same command
again, stat shows that the ctime has not changed unless it was necessary
to modify the permissions of a file or directory.

I am pretty happy about this solution and I intend to use it in cases
where there is a integrity-checker in place and no cfengine.

But while doing my tests, I noticed something strange about setfacl: if
the filesystem is mounted with extended ACLs enabled (on a ext3 fs), it
is possible to use setfacl to make changes to file permissions and CTIME
IS NEVER MODIFIED EVEN IF PERMISSIONS ARE MODIFIED.  I thought that this
was supposed to be impossible, but perhaps this is a known side-effect
("feature") of activating extended ACLs on ext3.

Can anyone else confirm this?  I am running etch with an ext3 filesystem
that was created in June 2008. This is my "uname -a":

	Linux mango 2.6.18-6-vserver-686 #1 SMP Mon Aug 18 11:11:15 UTC 2008 i686 GNU/Linux

#497514#90
Date:
2020-10-13 11:06:59 UTC
From:
To:
On Mon, 15 Sep 2008 11:22:41 +0200 Erik Rossen <rossen@rossen.ch> wrote:
Thing.
the
maybe ask
not?  I
if
act
for
liner
liner
and
writable
necessary
if
it
CTIME
this
effect
filesystem
2008 i686 GNU/Linux

I have another use-case for only attempting to make a change with chmod
if it is really necessary.

In a Debian postinst script (for VDR in this particular case) the
ownership of a directory (/var/lib/video) is changed - however I have
moved /var/lib/video to be a symlink to an NFS server. The permissions
are already set correctly, but as root can not (in this case) change an
NFS mounted file system, the chmod fails, even though it wanted to
change the owner to be the same as it already was.

A switch for chmod to say --only-if-needed or some such would avoid
this being an issue

John

#497514#95
Date:
2022-03-15 16:41:35 UTC
From:
To:

#497514#100
Date:
2022-05-16 15:07:08 UTC
From:
To:

#497514#105
Date:
2022-06-21 13:39:49 UTC
From:
To: