An important safety note about
chown and symlinks (also chmod and chgrp)
Today I had a little Twitter exchange about a little (or not so little) thing that is not as well known as it should be:
@thatcks: Ah yes, the eternal question: is it 'chown -Hr' or 'chown -hR' that I want?
(Answer: the second. Also, -h should be the default, at least with -R.)
@mrhoten: TIL I have run some pretty dang risky chown -R's and not even known it.
For those who haven't encountered this particular combination of
arguments for the
chown command, -R
is a recursive chown through a directory hierarchy, while -h is,
well, let me quote the manual (for GNU chown):
affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)
(Similar wording is in the FreeBSD chown manpage.)
Let me translate this. If you run plain '
chown -R user.group dirtree',
and the directory tree contains symlinks that point outside itself,
your recursive chown will change the ownership of the files that those
symlinks point to. Is there a symlink to
/etc/shadow? Well, you just
changed its ownership. A recursive
-h can do random
damage to owners and groups anywhere on your system.
Recursive chowns aren't the only time this comes up. Consider '
user.group *' in a directory, to fix ownership for the user. If there
are any symlinks, congratulations, you once again changed the ownership
of random files on your system. You should always use
chown unless you're sure you know what you're doing. You almost
never want to change the ownership of the target of a symlink.
(If you have a tangled chain of symlinks and you need to fix the
permissions of the real underlying file behind them all, generally
to find out what it is first.)
Naturally the same thing applies to the
chgrp command. The GNU
chmod command unfortunately lacks a
-h option, and will always
change permissions on the target of symlinks given on the command
line (which might happen in, for example, '
chmod g+r *').
does have a
-h option and you should always use it unless you're
Sidebar: The potential bad state of OpenBSD and
contains the following hair-raising statement about the
option (emphasis mine):
Treat symbolic links like other files: modify links instead of following them. The
-Roptions are mutually exclusive.
chown also has a -P argument, which is the default
behavior in '
chown -R'. This is described as:
-Roption is specified, no symbolic links are followed.
It's not clear what OpenBSD's manpage means by 'followed' here.
Are symbolic links that point to directories not descended into
but symbolic links are chown'd in general, or are symbolic links
entirely ignored, being neither chown'd nor descended into?
chown really does follow the POSIX
then the POSIX specification
is much clearer here and specifies the behavior we don't want:
-Roption is specified and a symbolic link is specified on the command line or encountered during the traversal of a file hierarchy,
chownshall change the owner ID (and group ID, if specified) of the symbolic link. The
chownutility shall not follow the symbolic link to any other part of the file hierarchy.
Update: I think I misread this and was wrong about the POSIX
behavior, because it specifies that with
-P, the symbolic link itself
is chown'd. That would make it the behavior we want.
chown really uses the POSIX behavior, then you can't safely
chown on OpenBSD to change the ownership of a directory tree. You
need to use a much more awkward
find command line to chown everything
that isn't a symlink.
(POSIX appears to implicitly forbid combining '
-h' and '
but that's crazy and may be a mistake in POSIX.)