Linux file permissions come down to three numbers and a handful of special bits, but the numbers trip people up because the math isn’t explained where you’d actually see it — on the command line. chmod 755, chmod 2775, umask 022 all make sense once you see where each digit comes from. This covers the actual bit math, plus the two gotchas that cause real incidents: chmod silently ignoring symlinks, and the sticky bit doing something completely different depending on whether it’s set on a file or a directory.
How chmod’s Numeric Mode Actually Works
A chmod numeric mode is up to four octal digits, and each one is a sum of three values: read is 4, write is 2, execute is 1. chmod 644 file.txt breaks down as 6 (4+2, read+write) for the owner, 4 (read only) for the group, and 4 (read only) for everyone else. chmod 755 script.sh gives the owner 7 (4+2+1, full access) and read-plus-execute (5) to the group and everyone else — the standard mode for a script or directory you want others to run or enter but not modify.
The fourth digit, when you include it, is where setuid, setgid, and the sticky bit live: setuid is 4, setgid is 2, and the sticky bit is 1. chmod 2755 /shared/scripts sets setgid (2) on top of the usual 755, and chmod 4755 /usr/bin/passwd-style commands are how setuid binaries like passwd let a normal user temporarily run as root to change their own password entry in /etc/shadow.
What Setuid and Setgid Actually Do
Setgid on a directory is the one worth remembering: any new file created inside inherits the directory’s group instead of the creating user’s primary group. That’s the standard fix for shared team directories where everyone’s files need to stay in the same group without each person manually running chgrp afterward.
⚠️ Important: Linux automatically clears the setgid bit on a regular file if the file’s group doesn’t match your effective group ID or one of your supplementary group IDs, unless you have elevated privileges. This is a real security guard, not a bug — it stops a chmod from silently granting elevated group execution to a file whose ownership doesn’t actually support it, per the chmod man page.
Directories behave differently from files here too: chmod preserves a directory’s setuid and setgid bits by default even when you don’t mention them. If you actually want to clear them with a numeric mode, you need a leading zero, a leading minus, or a leading equals sign — chmod 0755 dir clears both bits explicitly, where chmod 755 dir on its own leaves them alone.
The Sticky Bit Means Something Different on Files vs. Directories
On a directory, the sticky bit (mode 1000, the t in drwxrwxrwt) is what makes /tmp safe to be world-writable. It stops any user from deleting or renaming a file they don’t own inside that directory, even though everyone technically has write access to the directory itself — only the file’s owner (or the directory’s owner) can remove it. This is the exact mechanism, and it’s why /tmp can be 1777 instead of a security disaster.
On a regular file, the sticky bit meant something else entirely on older Unix systems: it told the kernel to keep the program’s compiled text image on the swap device so it would load faster the next time it ran. Modern Linux kernels ignore this behavior for regular files — if you see the sticky bit set on a plain file today, it’s either legacy cruft or a mistake, not a real optimization.
The Gotcha Nobody Reads Until It Bites: chmod and Symlinks
chmod does not change the permissions of a symbolic link itself. The underlying chmod system call can’t change a symlink’s own permissions on most systems, and even where it technically could, chmod deliberately ignores that setting and changes the permissions of whatever the link points to instead. If you run chmod 700 mylink expecting the link to become private, you’ve actually just changed the mode of the target file — which might be a shared file you didn’t mean to touch.
If you specifically need to affect the link and not its target, chmod -h (or --no-dereference) is the flag for that, while --dereference (the default) affects the referent. Get this backwards on a script that walks a directory tree with symlinks in it, and you can end up changing permissions on files well outside the directory you thought you were locking down.
chown: Changing Owner and Group Together
chown takes four distinct forms, and mixing them up is an easy mistake under time pressure. chown alice file changes only the owner, leaving the group untouched. chown alice:devs file changes both the owner and the group in one call. chown :devs file changes only the group — functionally identical to running chgrp devs file. And chown alice: file (owner followed by a bare colon, no group name) sets the owner to alice and resets the group to alice‘s own login group, which is easy to do by accident if you meant to type a group name after the colon and didn’t.
umask: Why New Files Don’t Show Up as 777
umask doesn’t touch existing files — it sets the file mode creation mask for the current shell, which subtracts permissions from every file created afterward in that same session. A umask of 022 is why a text editor that requests 666 (read-write for everyone) for a new file actually creates it as 644 (owner read-write, group and other read-only): the mask’s 022 removes write access for group and other from whatever the creating program asked for.
The mask only applies going forward. Running umask inside a subshell, a nohup invocation, or a find -exec doesn’t change the mask of the shell that launched it — each of those runs in its own execution environment, per the POSIX umask specification. If you set umask 077 at the top of a deployment script expecting it to lock down every file the script writes, confirm the mask is actually being inherited by whatever subprocess is doing the file creation, not just the parent shell.
Frequently Asked Questions
Q: What does chmod 777 actually do, and why is it a bad idea?
A: It grants read, write, and execute to the owner, group, and everyone else — full access for every user on the system. It’s occasionally used to quickly rule out permissions as the cause of an error, but leaving it in place on anything reachable by other users or the network turns a permissions problem into a security one.
Q: Why did chmod not change my symlink’s permissions?
A: By design. chmod follows symlinks and changes the target file’s mode, not the link’s own mode, unless you pass -h or --no-dereference.
Q: What’s the difference between the sticky bit on a file and on a directory?
A: On a directory, it restricts file deletion to the file’s owner (the /tmp behavior). On a regular file, it’s a legacy swap-caching hint that modern Linux kernels don’t act on.
Q: Does umask affect files that already exist?
A: No. It only changes the default permissions applied to files created after the mask is set, in the same shell session.
Q: How do I set setgid on a shared team directory?
A: chmod g+s /path/to/shared-dir, or chmod 2775 /path/to/shared-dir if you also want group write access. New files created inside inherit the directory’s group automatically.
Quick Summary:
– Numeric chmod is four octal digits: special bits (setuid 4 + setgid 2 + sticky 1), then owner, group, other — each a sum of read(4)/write(2)/execute(1)
– Setgid on a directory makes new files inherit the directory’s group; Linux clears setgid automatically if the file’s group doesn’t match your effective or supplementary groups
– The sticky bit means “only the owner can delete their own files” on a directory (the /tmp mechanism), but is an obsolete swap-caching hint on a regular file
– chmod changes a symlink’s target, not the link itself, unless you pass -h/--no-dereference
– umask only affects files created after it’s set, in the same shell — it does nothing to existing files or to a parent shell when set inside a subshell
Run umask with no arguments right now in your own shell before assuming what your next mkdir or file write will actually produce.