File permissions

There are three categories of file permissions for any given file: owner, group, and everyone else. Some of the more common file ownership commands are chown, chmod and chgrp.

chown is used to change the ownership of a file. It can be used as follows:

chown user:group path/to/file_or_directory # Change owner and group
chown user: path/to/file_or_directory # Change owner and group to have same _user_

chgrp on the other hand is used to modify just the group of a file:

chgrp group path/tp/file

The primary use of this is to change the group ownership of a file without modifying who owns it.

chmod is used to adjust file permissions more generally. It does not set user or group ownership, but defines how a user or group (or everyone else) can access the file. The command supports two types of notation: symbolic notation (u+x) or octal notation (755).

The general syntax of chmod is chmod [who] [operator] [permission] <file>, where:

[who][operator][permission]
u (user/owner)+ (add)r (read)
g (group)- (remove)w (write)
o (others)= (set)x (execute)
a (all)

Example

To give the owner for the script.sh file permission to execute, we might do:

chmod u+x script.sh

To set different permissions for group and owner, we can do:

chmod --recursive g+wx,o+x script.sh 

Octal notation for chmod works in the same way, except all three permissions are set at once using three digit numbers. The digits represent user/owner, group, and others respectively. Each of the digits is the sum of the permission values, which are:

PermissionValue
Read4
Write2
Execute1

Example

To allow the owner of a file to read/write/execute, allow group to just read/write, and everyone else to just read:

chmod 764 script.sh

Where the first 7 refers to the owner (4 + 2 + 1), while the 6 refers to the group (4 + 2), and 4 refers to every one else (4). Permissions would then show up as:

-rwxrw-r--  1 owner group  script.sh

File attributes

File attributes are an extended set of control that go beyond standard file permissions. The primary commands are lsattr and chattr to list and change the attributes respectively.

lsattr is useful to check whether protections like immutability1 or append-only are active on a file. The general flag options are -R (recurse), -a (all, including hidden files), -d (show dir attributes instead of contents).

The output of lsattr might look something like this:

 lsattr -adR /etc/myconfig/
----i--------------e-- /etc/myconfig/settings.conf
-----a-------------e-- /etc/myconfig/logs.log

Some different options in the output are (the man chattr for more):

LetterAttributesDescription
aappend-onlyFile can only be opened in append mode for writing
iimmutableFile cnanot be modified, deleted, or renamed
ssecure delectionWhen deleted, the kernel will overwrite its data blocks with 0
uundeletableThe file cannot be deleted (but can be modified)
Ano atime updateThe file’s access time doesn’t update when the file is read
ccompressedThe file is automatically compressed when written to disk
euses extentsIndicates that the file is using extents for mapping the blocks on disk

Note

An extent is a method to track where data lives on a disk used by modern filesystems. Rather than keeping track of individual blocks (especially when the files are fragmented), extents uses single records that describe the size and extent of a block.2

Whereas lsattr is used to list the attributes of a file, chattr is used to change or set them. The way it works is by using plus/minus signs to set or remove attributes. For instance, if we want to make a file immutable:

chattr +i ./myfile.md # add immutability
chattr -i ./myfile.md # remove immutability

Special permissions

Special permissions are used to temporarily grant users extra access under certain conditions. These are controlled by three primary concerns: setuid, setgit, and sticky bit.

setuid allows a program to run with the privileges of the file’s owner, rather than those of the user actually running the file. This is commonly used to allow regular users to run files that require elevated privileges. To setuid, use the command chmod u+s <file>.3

Example

To allow a file to always run as root, regardless of who created the file or who is running it:

sudo chown root:root script.sh
sudo chown u+s script.sh

Likewise, we can use setgid to allow a file to run with the permissions of the group. chmod g+s <file>. This is a far more common and useful thing done these days:

sudo groupadd project
sudo usermod -aG project alice
sudo usermod -aG project bob
 
sudo mkdir /srv/shared
sudo chown root:project /srv/shared
sudo chmod 2775 /srv/shared # the 2 here is the setgid bit
 
-> ls /srv/shared
drwxrwsr-x root project /srv/shared

This means that whenever alice or bob create files in /srv/shared the group ownership of those files will be project, rather than the users themselves:

alice$
touch file1
-rw-r--r-- alice project file1
 
bob$
touch file2
-rw-r--r-- bob project file2

For comparison, if we had not used setgid, file creation would look like this:

-rw-r--r-- alice alice file1
-rw-r--r-- bob bob file2

This would require regular chgrp calls to ensure everyone can access the files.

Note

When multiple people have write access to a directory we can set chmod +t <directory> to enforce a sticky bit. This is a special permission used to prevent deletion or renaming of files not owned. Setting this up means that different users can write to a directory, but can only delete their own files.

umask

umask us the user creation mask. It is used to set the default permissions for newly created files and directories in Linux.

It works by subtracting the defined permission bits (default of 022) from a set of starting bits. That is to say, new files are often created with default permissions of 666, while directories with 777.

When a user creates a new file, then, the permissions assigned to that file will be 666 - 022 for a resulting permission set of 644 (meaning the user creating the file can read/write, everyone else can only read).4

Common umask values are:

umaskFile permissions (666 & ~umask)Dir permissions (777 & ~umask)Meaning
000666rw-rw-rw-777rwxrwxrwxNo restrictions: everyone can read/write (and execute dirs). Generally unsafe.
022644rw-r--r--755rwxr-xr-xOwner full access; group/others read-only (files) or read/execute (dirs). Default on many distros.
027640rw-r-----750rwxr-x---Owner full access; group read-only; no access for others.
077600rw-------700rwx------Owner full access; group/others have no permissions. Very restrictive.
002664rw-rw-r--775rwxrwxr-xOwner/group full access; others read-only. Useful for shared group projects.

umask values can be set with both octal and symbolic notation:

# Change the mask symbolically to allow read permission for all users (the rest of the mask bits are unchanged):
    umask a+r
# Set the mask (using octal) to restrict no permissions for the file's owner, and restrict all permissions for everyone else:
    umask 077

umask is a per-user setting. To make it persistent, add it to your shell startup files (e.g. .bashrc, .bash_profile, or system-wide /etc/profile).

Footnotes

  1. Immutable files are those that cannot be modified, deleted, renamed, or have their contents name. In the context of Linux attributes, it means that these properties cannot be bypassed even by the root user.

  2. Note that some filesystems, like btrfs, will not show the e attribute in the output of lsattr. This is because chattr/lsattr were primarily written for extX filesystems. Additionally, in btrfs all files are extent-based already.

  3. Although this sounds great in theory, the Linux kernel does not honor setuid on interpreted scripts. This is because when running a script, such as a bash script, the kernel is invoking /bin/bash or what have you, which creates a security liability.

  4. The mechanism is not a literal subtraction. It is a bitwise mask that turns off the corresponding permission bits.