Featured image

Table of Contents Link to heading

File Ownership Model Link to heading

Every file and directory on a Linux system has two owners: a user owner and a group owner. Ownership determines which permission set applies when a user accesses the file.

  • The user owner is typically the account that created the file. Only the root user can change the user owner of a file.
  • The group owner defaults to the primary group of the user who created the file. The file owner (or root) can change the group to any group they belong to.

Internally, the operating system tracks ownership by UID (user ID) and GID (group ID), not by name. When you see a username in ls -l output, the system looked up the name from /etc/passwd using the stored UID.

ls -l /etc/nginx/nginx.conf
# -rw-r--r-- 1 root root 2657 Jan 10 09:23 /etc/nginx/nginx.conf
#              ^    ^
#              user group owner

Undefined Ownership Link to heading

If a user account is deleted or its UID is changed, files previously owned by that UID will display the numeric UID instead of a username — because no entry in /etc/passwd maps to that UID anymore. The same applies to group ownership and GIDs. This is called an orphaned file.

ls -l /home/deleted_user/
# -rw-r--r-- 1 1042 1042 1234 Jan 01 00:00 file.txt
#              ^    ^
#              raw UID/GID (no matching account in /etc/passwd)

To find files owned by a specific UID (useful after account deletion):

find / -uid 1042 2>/dev/null
find / -nouser 2>/dev/null      # files with no matching owner in /etc/passwd
find / -nogroup 2>/dev/null     # files with no matching group in /etc/group

Changing Ownership Link to heading

For verifying your current identity and group memberships, see id command.

newgrp: Temporarily Change Primary Group Link to heading

newgrp opens a new shell session with a different primary group — new files created in that session will be owned by the specified group instead of the user’s default primary group:

newgrp developers       # switch primary group to 'developers' for this session
# now create files — they will be owned by group 'developers'
exit                    # return to original shell and primary group

To permanently change a user’s primary group, root must modify the /etc/passwd entry:

sudo usermod --gid developers username

chgrp: Change Group Owner Link to heading

chgrp changes the group owner of files and directories. The root user can change any file’s group; regular users can only change group ownership to a group they belong to.

# Change group of a file
chgrp developers /srv/project/app.conf

# Change group recursively
chgrp -R developers /srv/project/

# Change group of a symlink (not its target)
chgrp -h developers /srv/project/current

# Match group of a reference file
chgrp --reference=/srv/reference.conf /srv/project/app.conf

chown: Change User and Group Owner Link to heading

chown changes the user owner, group owner, or both. Only root can change the user owner of a file. Regular users can use chown to change the group, but only to groups they belong to.

# Change user owner only
chown www-data /var/www/html/index.html

# Change group owner only (colon prefix, no user)
chown :webteam /var/www/html/
chown .webteam /var/www/html/        # dot syntax (equivalent)

# Change both user and group
chown www-data:webteam /var/www/html/
chown www-data.webteam /var/www/html/    # dot syntax

# Recursive (all files and subdirectories)
chown -R www-data:webteam /var/www/html/

# Change ownership of a symlink (not the target)
chown -h www-data:webteam /var/www/current

# Match ownership of a reference file
chown --reference=/var/www/html/index.html /var/www/html/style.css
Warning
chown -R on a large directory tree (especially / or /usr) is one of the most destructive commands you can run. A single mistyped path can change ownership of system binaries, making the system unbootable. Always double-check the path with ls before running chown -R as root.

Permission Model Link to heading

Read more at Long Display Listing

Linux file permissions use a 9-bit model — three sets of three bits, one set for each of: owner, group, others (world).

-rw-r--r-- 1 kali kali 45665 Nov 24 22:11 vimrc
 ↑↑↑↑↑↑↑↑↑
 │└──┘└──┘└──┘
 │ Owner Group Others
 File type

Permission Sets: Owner, Group, Others Link to heading

Set Who it applies to
Owner (user) The user account that owns the file
Group Any user who is a member of the file’s group owner
Others Everyone else (not the owner, not in the group)

Permissions are evaluated in order: owner → group → others. The first matching set applies — if you are the file owner, the owner permissions apply and the group/others sets are ignored entirely, even if those sets are more permissive.

Read Permission Link to heading

Context Effect
Regular file Process can open and read the file’s contents
Directory Process can list the directory’s contents (ls)

Without read on a directory, ls will fail — but you may still be able to access files inside if you know their names and have execute permission on the directory.

Write Permission Link to heading

Context Effect
Regular file Process can modify the file’s contents
Directory Process can create, rename, or delete files within the directory
Note
Write permission on a directory is what controls whether files can be added to or removed from it — not write permission on the files themselves. A user with write on a directory can delete any file inside it, even files they do not own and cannot read. This is why /tmp uses the sticky bit to prevent this.

Execute Permission Link to heading

Context Effect
Regular file Process can execute the file as a program
Directory Process can enter the directory (cd) and use it as part of a path

Directory execute permission is often called the search bit — it allows the directory to be traversed as part of a path resolution. Without it, even cat /path/to/dir/file fails if dir lacks execute, regardless of permissions on file itself.

Changing Permissions: chmod Link to heading

chmod modifies the permission bits of files and directories. Two syntaxes are supported — symbolic for clarity, numeric for scripting.

Symbolic Method Link to heading

Symbolic chmod uses three components: who + action + permission:

Who Meaning
u User owner
g Group owner
o Others
a All (equivalent to ugo)
Action Meaning
+ Add permission
- Remove permission
= Set exactly (replace current bits)
Permission Meaning
r Read
w Write
x Execute
X Execute only if directory or already executable by someone
# Add execute for the owner
chmod u+x script.sh

# Add read and write for owner
chmod u+rw file.txt

# Remove execute from group
chmod g-x binary

# Give everyone read and execute
chmod a+rx /usr/local/bin/tool

# Set others to match group permissions
chmod o=g file.txt

# Remove all permissions from others
chmod o= file.txt

# Recursive: add write for group and others
chmod -R g+w,o+w /srv/shared/

# Recursive: add read for all, execute for directories only
chmod -R a+rX /srv/data/

Numeric (Octal) Method Link to heading

Each permission bit has a numeric value. Sum the values for each set:

Bit Value Meaning
r 4 Read
w 2 Write
x 1 Execute
0 No permission

A three-digit octal number specifies permissions for owner, group, and others in order:

Numeric Symbolic Meaning
7 rwx Full access
6 rw- Read and write
5 r-x Read and execute
4 r-- Read only
3 -wx Write and execute
2 -w- Write only
1 --x Execute only
0 --- No permissions
chmod 755 script.sh     # rwxr-xr-x  (owner: full, group: r+x, others: r+x)
chmod 644 config.txt    # rw-r--r--  (owner: r+w, group: r, others: r)
chmod 600 private.key   # rw-------  (owner: r+w, group: none, others: none)
chmod 750 /srv/app/     # rwxr-x---  (owner: full, group: r+x, others: none)
chmod 700 ~/.ssh/       # rwx------  (owner: full, group: none, others: none)

Common permission patterns for sysadmins:

Pattern Octal Use case
rwxr-xr-x 755 Standard executable, public directory
rw-r--r-- 644 Standard configuration file
rw------- 600 Private key, sensitive config
rwxrwxr-x 775 Shared project directory
rwxrwxrwt 1777 World-writable with sticky bit (like /tmp)
rwsr-xr-x 4755 setuid executable
rwxr-sr-x 2755 setgid directory

Inspecting Permissions: stat Link to heading

stat provides more detailed file metadata than ls -l, including the octal permission representation:

stat /etc/passwd
# File: /etc/passwd
# Size: 2847            Blocks: 8          IO Block: 4096
# Device: fd00h/64768d  Inode: 1442        Links: 1
# Access: (0644/-rw-r--r--)  Uid: (0/root)  Gid: (0/root)
# Access: 2024-01-15 09:23:41
# Modify: 2024-01-10 14:32:18
# Change: 2024-01-10 14:32:18

# Show only the octal permissions and filename
stat --format="%a %n" /etc/passwd          # outputs: 644 /etc/passwd

# Show owner and group
stat --format="%U %G %n" /etc/passwd       # outputs: root root /etc/passwd

# Show file size in bytes
stat --format="%s %n" /etc/passwd

# Check a filesystem's stats
stat --file-system /var/log/

Default Permissions: umask Link to heading

When a new file or directory is created, the kernel starts with a maximum permission set and subtracts the umask — a bitmask of permissions to withhold:

  • Files default maximum: 666 (rw-rw-rw-) — execute is never granted by default
  • Directories default maximum: 777 (rwxrwxrwx)
File default:      666  (rw-rw-rw-)
Minus umask:      -022  (----w--w-)
Result:            644  (rw-r--r--)

Directory default: 777  (rwxrwxrwx)
Minus umask:      -022  (----w--w-)
Result:            755  (rwxr-xr-x)
umask               # display current umask (octal)
umask -S            # display in symbolic form (e.g., u=rwx,g=rx,o=rx)

# Change umask for the current session
umask 027           # new files: 640, new directories: 750
umask 077           # new files: 600, new directories: 700 (private)
umask 002           # new files: 664, new directories: 775 (group-writable)

Common umask values:

umask New files New directories Use case
022 644 755 Standard (most distributions default)
027 640 750 More restrictive — deny others entirely
077 600 700 Maximum privacy — deny group and others
002 664 775 Collaborative — allow group to write

The umask set in a shell session applies only to that session. For persistent umask changes:

  • Per-user: add umask 027 to ~/.bashrc or ~/.bash_profile
  • System-wide: add to /etc/profile or /etc/profile.d/umask.sh
  • PAM-based: configure in /etc/pam.d/ via the pam_umask module