The Linux Security Model#
Linux is a multi-user operating system. Every file, process, and resource is owned by a user and associated with a group. The permission system controls who can read, write, or execute each file.
This model is simple but effective:
- Users — individual accounts (human or service)
- Groups — collections of users that share access
- Permissions — rules on each file defining what users/groups can do
Users#
Types of users#
| Type | UID Range | Purpose |
|---|---|---|
| Root | 0 | Superuser — unrestricted access |
| System/service | 1–999 | Run background services (nginx, postgres) |
| Regular users | 1000+ | Human accounts |
Viewing user information#
# Current user
whoami
# Current user's ID and groups
id
# Details about any user
id mike
# All users on the system
cat /etc/passwdThe /etc/passwd file format:
mike:x:1000:1000:Mike:/home/mike:/bin/bash| Field | Meaning |
|---|---|
mike | Username |
x | Password stored in /etc/shadow |
1000 | User ID (UID) |
1000 | Primary group ID (GID) |
Mike | Comment/full name |
/home/mike | Home directory |
/bin/bash | Login shell |
Managing users#
# Create a user
sudo useradd -m -s /bin/bash newuser
# Create with specific options
sudo useradd -m -s /bin/bash -G sudo,docker -c "Jane Smith" jane
# Set/change password
sudo passwd newuser
# Modify a user
sudo usermod -aG docker mike # Add mike to docker group
sudo usermod -s /bin/zsh mike # Change shell
# Delete a user
sudo userdel newuser # Remove user, keep home directory
sudo userdel -r newuser # Remove user and home directory
# Lock/unlock an account
sudo usermod -L jane # Lock
sudo usermod -U jane # UnlockKey flags for useradd/usermod#
| Flag | Meaning |
|---|---|
-m | Create home directory |
-s | Set login shell |
-G | Supplementary groups |
-aG | Append to groups (usermod only — without -a, it replaces groups) |
-c | Comment (full name) |
-d | Home directory path |
-e | Account expiration date |
Groups#
Groups let you grant access to multiple users without setting permissions individually.
Viewing groups#
# Current user's groups
groups
# Groups for a specific user
groups mike
# All groups on the system
cat /etc/group
# Details about a group
getent group dockerManaging groups#
# Create a group
sudo groupadd developers
# Add a user to a group
sudo usermod -aG developers mike
# Remove a user from a group
sudo gpasswd -d mike developers
# Delete a group
sudo groupdel developersImportant: After adding a user to a group, they need to log out and back in (or run newgrp groupname) for the change to take effect.
Primary vs supplementary groups#
- Primary group — assigned at user creation, used as the default group for new files
- Supplementary groups — additional groups the user belongs to
# Check primary group
id -gn mike
# Check all groups
id -Gn mikeFile Permissions#
Every file has three permission sets:
-rwxr-xr-- 1 mike developers 4096 Jun 9 10:00 script.sh
│││ │││ │││
│││ │││ └── Others (everyone else)
│││ └──── Group (developers)
└────── Owner (mike)Permission types#
| Symbol | Permission | On files | On directories |
|---|---|---|---|
r | Read | View contents | List contents |
w | Write | Modify contents | Create/delete files inside |
x | Execute | Run as program | Enter (cd into) the directory |
- | None | No access | No access |
Reading permissions#
-rwxr-xr--| Position | Meaning |
|---|---|
- | File type (- = file, d = directory, l = link) |
rwx | Owner can read, write, execute |
r-x | Group can read and execute, not write |
r-- | Others can only read |
Changing Permissions with chmod#
Symbolic mode#
# Add execute for owner
chmod u+x script.sh
# Remove write for group and others
chmod go-w file.txt
# Set exact permissions
chmod u=rwx,g=rx,o=r script.sh
# Add read for everyone
chmod a+r file.txt| Symbol | Meaning |
|---|---|
u | User (owner) |
g | Group |
o | Others |
a | All (user + group + others) |
+ | Add permission |
- | Remove permission |
= | Set exact permission |
Numeric (octal) mode#
Each permission has a numeric value:
| Permission | Value |
|---|---|
| Read (r) | 4 |
| Write (w) | 2 |
| Execute (x) | 1 |
| None (-) | 0 |
Add the values for each set:
| Octal | Permissions | Meaning |
|---|---|---|
7 | rwx | Full access |
6 | rw- | Read and write |
5 | r-x | Read and execute |
4 | r-- | Read only |
0 | --- | No access |
chmod 755 script.sh # rwxr-xr-x (owner full, group/others read+execute)
chmod 644 file.txt # rw-r--r-- (owner read/write, group/others read)
chmod 700 private/ # rwx------ (owner only)
chmod 600 secret.key # rw------- (owner read/write only)Common permission patterns#
| Octal | Use case |
|---|---|
755 | Executable scripts, directories |
644 | Regular files (configs, documents) |
700 | Private directories |
600 | Private files (SSH keys, secrets) |
775 | Shared group directories |
664 | Shared group files |
Recursive permissions#
# Apply to directory and all contents
chmod -R 755 /var/www/html/
# Set directories to 755 and files to 644 (common for web)
find /var/www -type d -exec chmod 755 {} \;
find /var/www -type f -exec chmod 644 {} \;Changing Ownership with chown#
# Change owner
sudo chown mike file.txt
# Change owner and group
sudo chown mike:developers file.txt
# Change group only
sudo chown :developers file.txt
# or
sudo chgrp developers file.txt
# Recursive
sudo chown -R mike:developers /var/www/project/Special Permissions#
setuid (SUID)#
When set on an executable, it runs as the file owner, not the user who launched it:
# The passwd command has SUID — it runs as root so it can modify /etc/shadow
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root ... /usr/bin/passwdThe s in the owner execute position indicates SUID.
chmod u+s program
chmod 4755 programsetgid (SGID)#
On a file: runs as the file’s group. On a directory: new files inherit the directory’s group:
# Set SGID on a shared directory
chmod g+s /shared/projects/
chmod 2775 /shared/projects/
# Now any file created inside inherits the "projects" groupSticky bit#
On a directory: only the file owner (or root) can delete files, even if others have write permission:
# /tmp uses the sticky bit
ls -ld /tmp
# drwxrwxrwt ... /tmp
# Set sticky bit
chmod +t /shared/
chmod 1777 /shared/The t in the others execute position indicates the sticky bit.
sudo — Running Commands as Root#
Regular users can’t modify system files or manage services. sudo grants temporary elevated privileges.
# Run a single command as root
sudo apt update
# Open a root shell
sudo -i
# Run as a different user
sudo -u postgres psql
# Edit a file as root (use this instead of sudo vim)
sudoedit /etc/ssh/sshd_configThe sudoers file#
/etc/sudoers controls who can use sudo. Always edit it with visudo — it validates syntax before saving:
sudo visudoCommon entries:
# User mike can run any command as root
mike ALL=(ALL) ALL
# Group developers can restart nginx without a password
%developers ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx
# User deploy can run specific commands only
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp, /usr/bin/journalctl -u myappsudo vs su#
| Command | Action |
|---|---|
sudo command | Run one command as root |
sudo -i | Start a root login shell |
su - username | Switch to another user (needs their password) |
sudo su - username | Switch to another user (needs your sudo privilege) |
umask — Default Permissions for New Files#
The umask value determines what permissions are removed from new files:
# View current umask
umask
# 0022
# What this means:
# New files: 666 - 022 = 644 (rw-r--r--)
# New directories: 777 - 022 = 755 (rwxr-xr-x)# Set a more restrictive umask
umask 077
# New files: 600, new directories: 700Make it persistent by adding to ~/.bashrc.
Practical Examples#
Set up a shared project directory#
# Create group and directory
sudo groupadd webteam
sudo mkdir /var/www/project
sudo chown root:webteam /var/www/project
sudo chmod 2775 /var/www/project
# Add users to the group
sudo usermod -aG webteam mike
sudo usermod -aG webteam janeThe SGID bit (2) ensures new files inherit the webteam group.
Secure SSH keys#
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
chmod 600 ~/.ssh/configFind files with incorrect permissions#
# World-writable files (potential security issue)
find / -type f -perm -002 2>/dev/null
# SUID binaries (should be a short, known list)
find / -perm -4000 2>/dev/null
# Files not owned by any user
find / -nouser 2>/dev/nullBest Practices#
- Use groups to manage shared access instead of making files world-readable
- Apply the principle of least privilege — give the minimum permissions needed
- Never set 777 on anything — there’s always a better approach
- Use
sudofor individual commands rather than working in a root shell - Always use
visudoto edit the sudoers file — a syntax error can lock you out - Set SGID on shared directories so group ownership is inherited automatically
- Keep SSH keys at 600 — SSH refuses to use keys with loose permissions
- Audit SUID binaries periodically — an unexpected SUID binary is a red flag

