Skip to content

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 w and x on the directory, not w on the file.
  • r without x on a directory lists names but not their attributes or contents; x without r allows access to entries whose names you already know.
  • Every directory on a path needs x for the class that applies, or the path can't be followed.
  • A script needs r as well as x, 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 nosuid ignore 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_FSETID capability 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
chmod 640 app.conf
chmod u+x,go-w deploy.sh
chmod -R u=rwX,g=rX,o= /srv/project

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
sudo chown www-data:www-data /srv/www/index.html
sudo chown -R alice: /home/alice

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.

chgrp developers report.txt

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) and chgrp(1), from GNU coreutils 9.7, and the uutils coreutils 0.10.0 --help output; the GNU coreutils manual's File permissions chapter
  • chmod(2), umask(2), path_resolution(7) and capabilities(7) from the Linux man-pages project
  • acl(5), getfacl(1) and setfacl(1), from acl 2.4.0
  • pam_umask(8) and login.defs(5)
  • stat(1) and ls(1)