File permissions and modes¶
Checked against GNU coreutils 9.7 (Debian 13), 9.5 (AlmaLinux 10 and Rocky Linux 10) and 9.12 (Arch and Gentoo), uutils coreutils 0.10.0 (Ubuntu 26.04), and acl 2.4.0 (Arch and Gentoo), on Linux 6.12 and later.
Ubuntu 26.04 ships chmod, chown and chgrp from uutils coreutils, a reimplementation in Rust, instead of GNU coreutils.
The modes, the special-bit behaviour and the options listed here are the same in both, except where a section says otherwise.
Synopsis¶
chmod [OPTION]... MODE[,MODE]... FILE...
chmod [OPTION]... OCTAL-MODE FILE...
chmod [OPTION]... --reference=RFILE FILE...
chown [OPTION]... [OWNER][:[GROUP]] FILE...
chown [OPTION]... --reference=RFILE FILE...
chgrp [OPTION]... GROUP FILE...
chgrp [OPTION]... --reference=RFILE FILE...
umask [-S] [MODE]
getfacl [OPTION]... FILE...
setfacl [OPTION]... {-m|-M|-x|-X} ACL_SPEC... FILE...
Description¶
Every file and directory (every inode) has an owning user (UID), an owning group (GID) and a 12-bit mode: nine permission bits and three special bits. The kernel compares the mode with the identity of the process that asks for access. It checks exactly one permission class: user if the process's filesystem UID is the file's owner, otherwise group if the file's group is the process's filesystem GID or one of its supplementary groups, otherwise other. The classes don't combine: an owner whose user bits deny an access is refused even if the group or other bits allow it.
A process with the CAP_DAC_OVERRIDE capability, which includes root, bypasses read and write checks, and bypasses execute checks on directories.
It may execute a regular file only if at least one of the three execute bits is set.
Permission bits¶
| Bit | Symbol | Octal | On a regular file | On a directory |
|---|---|---|---|---|
| Read | r |
4 | Read the contents | List the names of the entries (ls) |
| Write | w |
2 | Change the contents (including truncating it) | Create, delete and rename entries; needs x as well |
| Execute | x |
1 | Run the file as a program or script | Enter it and access entries by name (cd, open a known path) |
Notes:
- Deleting or renaming a file is a change to its directory: it needs
wandxon the directory, notwon the file. rwithoutxon a directory lists names but not their attributes or contents;xwithoutrallows access to entries whose names you already know.- Every directory on a path needs
xfor the class that applies, or the path can't be followed. - A script needs
ras well asx, because the interpreter reads it.
Octal modes¶
An octal mode is up to four digits. The last three give the user, group and other permissions, each the sum of 4 (read), 2 (write) and 1 (execute). An optional leading digit sets the special bits.
| Digit position | Meaning | Values |
|---|---|---|
| 1st (optional) | Special bits | 4 = setuid, 2 = setgid, 1 = sticky |
| 2nd | User (owner) | 0–7 |
| 3rd | Group | 0–7 |
| 4th | Other | 0–7 |
| Digit | Permissions | Digit | Permissions |
|---|---|---|---|
| 0 | --- |
4 | r-- |
| 1 | --x |
5 | r-x |
| 2 | -w- |
6 | rw- |
| 3 | -wx |
7 | rwx |
Common modes:
| Mode | Symbolic | Typical use |
|---|---|---|
644 |
rw-r--r-- |
Ordinary file |
640 |
rw-r----- |
Configuration file readable by a service's group |
600 |
rw------- |
Private file, such as an SSH private key |
755 |
rwxr-xr-x |
Program, script, or ordinary directory |
750 |
rwxr-x--- |
Directory for the owner and one group |
700 |
rwx------ |
Private directory, such as ~/.ssh |
440 |
r--r----- |
Files in /etc/sudoers.d/ |
1777 |
rwxrwxrwt |
Shared temporary directory (/tmp) |
2775 |
rwxrwsr-x |
Shared project directory |
4755 |
rwsr-xr-x |
Setuid program (/usr/bin/passwd) |
chmod (GNU and uutils) keeps the setuid and setgid bits of a directory when you give a mode of three or four digits that doesn't mention them; chmod 755 and chmod 0755 leave a setgid directory setgid.
To clear them numerically, give five digits with a leading zero, such as 00755, or use the symbolic g-s and u-s.
Symbolic modes¶
A symbolic mode is one or more clauses separated by commas.
Each clause is [WHO]OPERATOR[PERMISSIONS], and several operator and permission pairs may follow one WHO.
| Part | Value | Meaning |
|---|---|---|
| WHO | u |
User (owner) |
g |
Group | |
o |
Other | |
a |
All three; also the meaning when WHO is omitted, except that bits set in the umask aren't changed | |
| OPERATOR | + |
Add the permissions |
- |
Remove the permissions | |
= |
Set exactly these permissions, clearing the others for WHO | |
| PERMISSIONS | r, w, x |
Read, write, execute |
X |
Execute, only if the file is a directory or already has an execute bit for some class | |
s |
Setuid (with u) or setgid (with g) |
|
t |
Sticky (restricted deletion) | |
u, g, o |
Copy the current permissions of that class, as in g=u |
Examples of the notation:
| Mode | Effect |
|---|---|
u+x |
Add execute for the owner |
go-w |
Remove write for group and other |
u=rw,g=r,o= |
Same as octal 640 |
a+rX |
Make readable by everyone; add execute only to directories and already-executable files |
g=u |
Give the group the same permissions as the owner |
g+s |
Set the setgid bit |
+t |
Set the sticky bit |
Special bits¶
| Bit | Octal | On an executable file | On a directory | In ls -l |
|---|---|---|---|---|
| setuid | 4000 |
The program runs with the file owner's UID as its effective UID | No effect on Linux | s in the user execute position; S if the user execute bit is clear |
| setgid | 2000 |
The program runs with the file's group as its effective GID | New entries inherit the directory's group; new subdirectories also inherit the setgid bit | s in the group execute position; S if the group execute bit is clear |
| sticky | 1000 |
No effect on Linux | Restricted deletion: only the entry's owner, the directory's owner or a privileged process may delete or rename an entry | t in the other execute position; T if the other execute bit is clear |
Notes:
- Linux ignores setuid and setgid on scripts that start with
#!; they work only on compiled programs. - Filesystems mounted with
nosuidignore setuid and setgid on files. - When the owner or group of a non-directory changes, Linux clears its setuid bit, and clears its setgid bit if the group execute bit is set. This happens even when root runs
chown. Directories keep both bits. - When a process without the
CAP_FSETIDcapability writes to a file, Linux clears the file's setuid bit, and its setgid bit if the group execute bit is set.
The ls -l mode string¶
ls -l and stat -c %A show the mode as ten characters, optionally followed by one more:
-rwxr-x---+
│└┬┘└┬┘└┬┘│
│ │ │ │ └── + : the file has an extended ACL; . : it has an SELinux context and no ACL
│ │ │ └──── other permissions
│ │ └─────── group permissions
│ └────────── user (owner) permissions
└──────────── file type
| Type character | File type |
|---|---|
- |
Regular file |
d |
Directory |
l |
Symbolic link |
c |
Character device |
b |
Block device |
p |
Named pipe (FIFO) |
s |
Socket |
Symbolic links always show rwxrwxrwx; Linux ignores their permissions and checks those of the target.
stat -c '%a %A %U:%G' FILE prints the octal mode, the mode string, and the owner and group.
umask¶
The umask is a per-process mask of permission bits that new files and directories don't get.
A program that creates a file requests a mode, usually 0666 for files and 0777 for directories, and the kernel clears the bits that are set in the umask.
Children inherit the umask, and umask is a shell built-in because it must change the shell's own value.
| umask | New file | New directory |
|---|---|---|
0022 |
0644 (rw-r--r--) |
0755 (rwxr-xr-x) |
0002 |
0664 (rw-rw-r--) |
0775 (rwxrwxr-x) |
0027 |
0640 (rw-r-----) |
0750 (rwxr-x---) |
0077 |
0600 (rw-------) |
0700 (rwx------) |
The umask never adds permissions: a file created with mode 0666 never becomes executable.
umask without arguments prints the current value in octal; umask -S prints it in symbolic form, such as u=rwx,g=rx,o=rx.
A symbolic argument such as umask g-w describes permissions to allow, not bits to mask.
Default umask for an ordinary user logging in over SSH, as observed on the verification labs:
| Distribution | Default | Notes |
|---|---|---|
| Debian 13, Ubuntu 26.04 | 0002 |
Set at login by pam_umask, which clears the group bits from the mask for a user whose private group has the same name (USERGROUPS_ENAB yes in /etc/login.defs) |
| AlmaLinux 10, Rocky Linux 10 | 0022 |
/etc/login.defs contains UMASK 022 |
| Arch | 0022 |
/etc/login.defs contains UMASK 022 |
| Gentoo | 0022 |
/etc/login.defs contains UMASK 022 |
A directory with a default ACL (see below) replaces the umask for entries created inside it.
chmod¶
Changes the mode of each file.
Only the file's owner, or a process with CAP_FOWNER, may change the mode.
If an unprivileged owner sets the setgid bit on a file whose group the owner isn't a member of, the kernel silently clears it.
| Option | Description |
|---|---|
-R, --recursive |
Change files and directories recursively |
-c, --changes |
Report only the files whose mode changed |
-v, --verbose |
Report every file processed |
-f, --silent, --quiet |
Suppress most error messages |
--reference=RFILE |
Copy the mode of RFILE |
--preserve-root |
Refuse to operate recursively on / |
-h, --no-dereference |
Change a symbolic link itself rather than its target (no effect on Linux, where links have no modes) |
-H, -L, -P |
With -R: follow symbolic links to directories given on the command line (-H), all symbolic links to directories (-L), or none (-P). The default is -H in GNU chmod and -P in uutils chmod, as their --help output states |
chown¶
Changes the owner and, optionally, the group of each file.
Only a privileged process (CAP_CHOWN) may change the owner.
The file's owner may change its group to any group the owner is a member of.
| Argument form | Effect |
|---|---|
OWNER |
Change the owner only |
OWNER:GROUP |
Change the owner and the group |
OWNER: |
Change the owner, and the group to the owner's login group |
:GROUP |
Change the group only, like chgrp |
Owners and groups may be given as names or as numeric IDs.
| Option | Description |
|---|---|
-R, --recursive |
Operate on files and directories recursively |
-h, --no-dereference |
Change a symbolic link itself rather than its target |
--from=CURRENT_OWNER:CURRENT_GROUP |
Change only files whose current owner and group match; either part may be omitted, and when both are given, both must match |
--reference=RFILE |
Copy the owner and group of RFILE |
-c, -v, -f, --preserve-root |
As for chmod |
-H, -L, -P |
With -R: follow symbolic links to directories given on the command line (-H), all symbolic links to directories (-L), or none (-P). The default is -P in both GNU and uutils chown |
chgrp¶
Changes the group of each file.
It is equivalent to chown :GROUP.
The options -R, -h, -c, -v, -f, --reference, --preserve-root, -H, -L and -P behave as they do for chown, including the default of -P.
Access control lists¶
POSIX access control lists (ACLs) extend the mode with entries for additional named users and groups.
ext4, XFS and Btrfs support them without special mount options.
The getfacl and setfacl commands come from the acl package, which isn't installed by default on Debian, Ubuntu, AlmaLinux or Rocky Linux; it is installed on Arch and Gentoo (sys-apps/acl).
ACL entries¶
| Entry | Text form | Meaning |
|---|---|---|
| Owner | user::rwx |
The user permission bits of the mode |
| Named user | user:alice:rwx |
Permissions for the user alice |
| Owning group | group::r-x |
Permissions for the file's group |
| Named group | group:developers:rwx |
Permissions for the group developers |
| Mask | mask::rwx |
Upper limit for named users, the owning group and named groups |
| Other | other::r-- |
The other permission bits of the mode |
| Default | default:user:alice:rwx |
On a directory only: copied into the ACL of entries created inside it |
user, group, mask, other and default may be abbreviated to u, g, m, o and d.
When a file has an extended ACL, the group bits shown by ls -l are the mask, not the owning group's entry, and chmod g=… changes the mask.
Lowering the mask limits every named entry; getfacl then shows the effective permissions after a #effective: comment.
$ getfacl report.txt
# file: report.txt
# owner: labuser
# group: labuser
user::rw-
user:alice:rwx #effective:r-x
group::r--
mask::r-x
other::r--
getfacl¶
| Option | Description |
|---|---|
-a, --access |
Show only the access ACL |
-d, --default |
Show only the default ACL |
-c, --omit-header |
Omit the # file, # owner and # group comment lines |
-e, --all-effective |
Show the effective permissions for every entry |
-n, --numeric |
Show numeric user and group IDs |
-p, --absolute-names |
Don't strip the leading / from path names |
-R, --recursive |
List directories recursively |
setfacl¶
| Option | Description |
|---|---|
-m ACL_SPEC, --modify=ACL_SPEC |
Add or change entries |
-M FILE, --modify-file=FILE |
Add or change entries read from a file (- for standard input) |
-x ACL_SPEC, --remove=ACL_SPEC |
Remove entries (give them without permissions, as in u:alice) |
-X FILE, --remove-file=FILE |
Remove entries read from a file |
-b, --remove-all |
Remove all extended entries, leaving the mode bits |
-k, --remove-default |
Remove the default ACL |
-d, --default |
Apply the operation to the default ACL |
--set=ACL_SPEC |
Replace the whole ACL |
--set-file=FILE |
Replace the whole ACL with entries read from a file (- for standard input) |
--mask |
Recalculate the mask, even if a mask entry was given explicitly |
-n, --no-mask |
Don't recalculate the mask |
-R, --recursive |
Apply to files and directories recursively |
-L, --logical |
With -R: follow symbolic links to directories |
-P, --physical |
With -R: don't follow any symbolic links, including those given as arguments. Without -L or -P, setfacl -R follows symbolic links given as arguments and skips those found inside directories |
--restore=FILE |
Restore ACLs saved with getfacl -R, the inverse of that command |
--test |
Show the result without changing anything |
setfacl -m u:alice:rw report.txt # give alice read and write
setfacl -m g:developers:rwX -R /srv/project
setfacl -d -m g:developers:rwX /srv/project # inherited by new entries
setfacl -x u:alice report.txt # remove alice's entry
setfacl -b report.txt # remove all extended entries
getfacl report.txt | setfacl --set-file=- copy.txt # copy an ACL
cp -a, cp --preserve=all, mv within one filesystem, and tar --acls keep ACLs; plain cp doesn't.
Files¶
| Path | Purpose |
|---|---|
/etc/login.defs |
UMASK, USERGROUPS_ENAB and HOME_MODE defaults used by useradd, login and pam_umask |
/etc/pam.d/ |
PAM configuration; pam_umask sets the umask at login where it's configured |
/etc/profile, ~/.profile, ~/.bashrc |
Shell start-up files that may set the umask |
See also¶
chmod(1),chown(1)andchgrp(1), from GNU coreutils 9.7, and the uutils coreutils 0.10.0--helpoutput; the GNU coreutils manual's File permissions chapterchmod(2),umask(2),path_resolution(7)andcapabilities(7)from the Linux man-pages projectacl(5),getfacl(1)andsetfacl(1), fromacl2.4.0pam_umask(8)andlogin.defs(5)stat(1)andls(1)
Related¶
- Tutorial: First steps on a Linux server
- How-to guide: How to grant a user sudo access
- Explanation: Users, groups and permissions