Why does chown reset/remove the SUID bit and reset capabilities?

This command:

sudo chown -R root:root directory

will remove the SUID bit and reset all capabilities for files. I wonder why it’s done silently and it’s not mentioned in the man page. Weirdly the GUID bit is not removed. And it doesn’t matter who the file or directory belonged to prior to running this command.

Also SUID/GUID bits are not removed for directories (thought they are useless in this case).

Presumably it’s done in the name of security but to me it must not be done silently.

This gets even worse:

$ setcap cap_sys_rawio,cap_sys_nice=+ep test
$ getcap -v test 
test cap_sys_rawio,cap_sys_nice=ep

$ chown -c -v -R 0:0 .
ownership of './test' retained as root:root
ownership of '.' retained as root:root

$  getcap -v test 
test

The SUID bit for the test file is removed completely silently. It’s as if the command is doing a lot more than requested.

The permissions and capability sets aren’t cleared by the chown utility, they’re cleared by the chown system call (on Linux):

When the owner or group of an executable file is changed by an
unprivileged user, the S_ISUID and S_ISGID mode bits are cleared.
POSIX does not specify whether this also should happen when root
does the chown(); the Linux behavior depends on the kernel
version, and since Linux 2.2.13, root is treated like other
users. In case of a non-group-executable file (i.e., one for
which the S_IXGRP bit is not set) the S_ISGID bit indicates
mandatory locking, and is not cleared by a chown().

When the owner or group of an executable file is changed (by any
user), all capability sets for the file are cleared.

As alluded to above, this is partially specified by POSIX:

Unless chown is invoked by a process with appropriate privileges, the set-user-ID and set-group-ID bits of a regular file shall be cleared upon successful completion; the set-user-ID and set-group-ID bits of other file types may be cleared.

If it were to inform the user about this, the chown utility would have to explicitly check for further changes made to files’ metadata when it invokes the chown function.

As far as the rationale is concerned, I suspect it’s to reduce the potential for gotchas for the system administrator — chown root:root on Linux can be considered as safe, even if a user prepared a setuid binary ahead of time.

The GNU chown man page doesn’t mention this behaviour, but as is often the case with GNU software, the man page documents the utility only partially; its “SEE ALSO” section points to the system call documentation (which is admittedly overkill for most users) and the info page, which does describe this behaviour:

The chown command sometimes clears the set-user-ID or set-group-ID permission bits. This behavior depends on the policy and functionality of the underlying chown system call, which may make system-dependent file mode modifications outside the control of the chown command. For example, the chown command might not affect those bits when invoked by a user with appropriate privileges, or when the bits signify some function other than executable permission (e.g., mandatory locking). When in doubt, check the underlying system behavior.

(I’m limiting this to Linux based on your tags on the question; since Linux restricts owner changes to privileged processes, there are fewer security implications than on some other Unix-style systems. See explanation on chown(1) POSIX spec for details.)

Answered By: Stephen Kitt