Ownership
Every file and directory on a Linux system carries exactly two ownership fields in its inode: a numeric user ID (UID) and a numeric group ID (GID). The kernel stores numbers, not names — alice and developers are resolved from /etc/passwd and /etc/group only when a tool prints them for you. Ownership is the first thing the kernel checks when a process touches a file: it picks one of three permission classes — owner, group, or other — by testing the process's UID against the file's UID first, then its GIDs against the file's GID, and applies that one class's bits.
That makes ownership the anchor of the whole permission model — the bits in rwxr-x--- mean nothing until you know who owns the file. Get ownership wrong and the symptoms are familiar: a web server returning 403 on files it cannot read, a deploy that runs as root and leaves a directory the application user can no longer write, or a shared project tree where half the files belong to the wrong group. You change ownership with two commands, chown and chgrp, but the traps live in recursion, symlinks, copies, and who is even allowed to make the change.
User Owner and Group Owner
The user owner is usually the account that created the file; the group owner defaults to the creating process's primary group, or to the directory's group when that directory has the setgid bit. ls -l prints both in its third and fourth columns, while stat shows them alongside the numeric IDs that actually live on disk.
# names resolved from /etc/passwd and /etc/group ls -l app.log -rw-r----- 1 www-data adm 8042 May 30 03:11 app.log # the raw numbers the kernel stores, plus the name lookups stat -c '%U(%u) %G(%g)' app.log www-data(33) adm(4)
chown sets the user owner, chgrp sets the group, and chown does both at once with user:group. A trailing colon (chown alice:) sets the group to the new owner's primary group; a leading colon (chown :developers) changes only the group and is identical to chgrp developers. You can pass names or raw numeric IDs — numbers matter when a UID exists on disk but has no matching entry in /etc/passwd, which is routine on extracted archives and bind-mounted container volumes.
# set user and group together chown www-data:www-data /var/www/site # group only — these two are equivalent chown :developers report.csv chgrp developers report.csv # numeric IDs: works even with no passwd entry chown 1000:1000 /mnt/data/file
Recursive Ownership and Symlink Traps
chown -R descends a directory tree and rewrites ownership on everything beneath it. This is where the symlink behavior bites. By default chown dereferences a symlink given on the command line and changes the target's ownership, not the link's; you need -h to affect the link itself. That default rarely matters for a lone link, because the link's own ownership is cosmetic — on Linux the permission check uses the target's owner, not the link's. Inside a recursive walk the three flags -H, -L, and -P decide what happens to links the walk encounters, and the wrong one will reach outside the tree you meant to touch.
| Flag | Effect during -R | Risk |
|---|---|---|
-P (default) | Operate on symlinks themselves, never follow them | Safe; link targets are untouched |
-H | Follow only links named on the command line, not ones found inside | One level of reach |
-L | Follow every symlink and recurse into linked directories | Can rewrite ownership far outside the tree |
The classic accident is chown -R --dereference (or -L) on a tree that contains a symlink to /etc or to another user's home — the walk follows the link and re-owns files you never intended to touch. Keep the default -P unless you have a concrete reason to follow links, and use chown -h when you specifically want to change a single symlink's own ownership without dereferencing it.
Ownership on Copy versus Move
Copy and move treat ownership oppositely, and the difference is a frequent source of "why is this file suddenly owned by root" tickets. mv within the same filesystem only relinks the inode, so the file keeps its original UID, GID, timestamps, and permissions untouched. cp creates a brand-new inode, so the copy is owned by whoever ran cp and gets a fresh mtime, with permissions filtered through the process umask.
# root copies a user file: the copy becomes root-owned cp /home/alice/notes.txt /backup/ stat -c '%U %G' /backup/notes.txt root root # -a (archive) = -dR --preserve=all: keep owner, group, times, mode cp -a /home/alice/notes.txt /backup/ # or preserve specific attributes only cp --preserve=ownership,timestamps notes.txt /backup/
Preserving ownership on copy still obeys the privilege rules: only root can recreate a copy owned by a different user, so an unprivileged cp -a across users silently falls back to the caller's UID for files it cannot assign. When a move crosses filesystem boundaries, mv degrades to copy-then-delete and inherits exactly the same ownership reset as cp — a same-disk mv preserves owner, a cross-disk mv may not.
Who May Change Ownership
Linux deliberately forbids unprivileged users from giving files away. Changing a file's user owner requires the CAP_CHOWN capability, which in practice means root (or sudo). A regular user cannot chown their own file to another account, even one they belong to — the rule closes a class of attacks where a user dumps a setuid binary or a quota-consuming file onto someone else's name.
The group is slightly looser: the file's owner may chgrp it to any group they are a member of, without root. So chown alice:developers file needs root to set the user part, but chgrp developers file succeeds for Alice alone if she is in developers. Note one sharp edge: a chown on an executable clears its setuid and setgid bits — since Linux 2.2.13 this happens even when root runs the chown — so re-owning a setuid binary quietly drops its privilege escalation, a guard against re-owning a root-setuid program to yourself.
- Running
chown -R www-data:www-data /after a typo'd path — re-owning the entire root filesystem breakssudo, SSH host keys, and/etc/shadowownership, and there is no single command to undo it cleanly. - Using
chown -R -L(or--dereference) on a tree that contains a symlink to/etcor another home directory — the walk follows the link and rewrites ownership well outside the directory you targeted. - Copying files into place as
rootwith plaincpand forgetting that the result is root-owned — the application user then gets 403/permission-denied on assets it was supposed to read or write. - Assuming a cross-filesystem
mvpreserves ownership the way a same-diskmvdoes — it degrades to copy-then-delete and resets owner, group, and mtime to the caller. - Editing
/etc/passwdor deleting a user without reassigning their files, leaving orphaned inodes owned by a bare numeric UID that a lateruseraddcan silently inherit. - Expecting a regular user to be able to
chowna file to a teammate — only root can change the user owner, so scripts that assume it work in testing as root and fail in production. - Relying on a symlink's own ownership for access control — the kernel checks the target's owner, so tightening the link's UID changes nothing about who can read the file.
- Default to
chown -Rwithout-L; the-Pbehavior is correct for almost every tree, and follow links only when you have verified there is no path out of the directory. - Add
--from=olduser:oldgroupto a recursivechownso it rewrites only files currently owned by the expected identity and skips everything else — a guardrail against re-owning the wrong tree. - Use
cp -a(or--preserve=ownership,timestamps,mode) whenever a copy must keep its identity, such as backups and migrations, and run it asrootso cross-user ownership is actually preserved. - Set the setgid bit on shared directories (
chmod g+s) so new files inherit the directory's group automatically, instead of chasing ownership with manualchgrpafter every write. - Manage service file ownership declaratively —
systemd-tmpfilesentries or your config-management tool — rather than ad-hocchownin deploy scripts that drift between hosts. - When deleting an account, run
userdeland then reassign or remove its files withfind / -uid <old> -exec chown newowner {} +so no orphaned UID lingers for the next user to inherit. - Confirm ownership with
stat -c '%U(%u) %G(%g)'after any bulk change; numeric IDs reveal mismatches that name lookups hide when an account is missing from/etc/passwd.
takeown and icacls; ownership is one entry in a richer access-control list, not a single UID/GID pairmacOS — same BSD chown/chgrp model on APFS, plus layered ACLs managed with chmod +aFreeBSD — the original BSD chown where user:group and user.group separators both work and behavior matches the GNU tool closelyKnowledge Check
Alice owns report.csv and is a member of the developers group. Which change can she make without sudo?
chgrp developers report.csv— the owner may set the group to any group she belongs tochown bob report.csv— the owner may always reassign her own files to another userchown bob:developers report.csv— changing the group lets her change the user owner too- None — every ownership change on Linux requires root
root copies a user's file with plain cp /home/alice/data /backup/. Who owns the copy, and why?
root—cpcreates a new inode owned by the caller; preserving the original owner needscp -aor--preserve=ownershipalice—cpalways preserves the source file's owner and group on the brand-new copy, with no extra flags needed at allroot, because thecpcommand always strips ownership down to root regardless of which flags you pass italice, because the destination directory's group is inherited and carries the original user owner across with it
Why is chown -R -L on a directory tree more dangerous than the default chown -R?
-Lfollows every symlink and recurses through it, so the walk can rewrite ownership of files outside the tree you targeted-Lmakes the command run faster but silently skips any files it cannot lock, leaving the directory tree only half-changed-Lchanges ownership of the symlinks themselves rather than their targets, which breaks every one of the links permanently-Lapplies the ownership change only to directories in the tree and silently ignores every regular file it walks past
A same-disk mv data.log /var/log/ keeps the file's owner, but a mv of the same file to a different filesystem resets it. What explains the difference?
- A same-filesystem move just relinks the existing inode; a cross-filesystem move degrades to copy-then-delete, making a new inode owned by the caller
- mv always resets ownership to the caller, and the same-disk case only appears to preserve the original owner because the result is still cached in memory
- Cross-filesystem moves quietly elevate themselves to run as root, and that forced privilege is what stamps root ownership onto the result
- The destination filesystem's mount options override the file's stored UID on every move, and the same-disk case simply reuses identical options
You got correct