Skip to content
elephantoo

Permissions & ownership

Lesson 8 of 31 16 min read

rwx for user, group and others, chmod in symbolic and octal form, chown, umask and special bits.


Linux was built as a multi-user system from day one. Every file and directory has an owner, a group and a set of permissions that decide who can read, write or execute it. Understanding them prevents both "Permission denied" frustration and dangerous security holes.

Reading permissions#

Terminal
mkdir demo && cd demo
echo 'echo "Hello from a script"' > hello.sh
echo "secret" > notes.txt
mkdir shared
ls -l
Output
total 12
-rw-r--r-- 1 ada ada   27 Oct  1 11:02 hello.sh
-rw-r--r-- 1 ada ada    7 Oct  1 11:02 notes.txt
drwxr-xr-x 2 ada ada 4096 Oct  1 11:02 shared

The first column breaks down like this:

Output
-  rw-  r--  r--
│   │    │    └─ others: everyone else
│   │    └─ group: members of the file's group
│   └─ user: the file's owner
└─ type: - file, d directory, l symlink

Then come the link count, the owner (ada) and the group (ada). On Ubuntu, every user gets a personal group with the same name.

LetterOn a fileOn a directory
r readview the contentslist the names inside (ls)
w writechange the contentscreate, delete and rename entries inside
x executerun it as a programenter it (cd) and access entries by name
-permission not granted

Note the directory rule. Deleting a file needs write permission on the directory, not on the file itself.

Running a script needs x#

Terminal
./hello.sh
Output
bash: ./hello.sh: Permission denied
Terminal
chmod u+x hello.sh
ls -l hello.sh
./hello.sh
Output
-rwxr--r-- 1 ada ada 27 Oct  1 10:53 hello.sh
Hello from a script

chmod: symbolic mode#

chmod who±what file:

  • who: u (user/owner), g (group), o (others), a (all)
  • operator: + add, - remove, = set exactly
  • what: r, w, x
Terminal
chmod go-r notes.txt        # group and others can no longer read
chmod g+w shared            # group members may create files in shared/
chmod a=r notes.txt         # everyone read-only, nothing else
chmod u+w,go= notes.txt     # owner adds write; group and others get nothing
ls -l notes.txt
Output
-rw------- 1 ada ada 7 Oct  1 10:53 notes.txt

chmod: octal (numeric) mode#

Each permission has a value. r = 4, w = 2, x = 1, and you add them up per group:

DigitsMeaningTypical use
755rwxr-xr-xscripts, programs, directories
644rw-r--r--normal files, web pages
700rwx------private directories (~/.ssh)
600rw-------private files (SSH keys, .env secrets)
640rw-r-----config readable by a service's group
775 / 664group-writableshared project folders
Terminal
chmod 600 notes.txt
chmod 755 hello.sh
stat -c '%A %a %n' notes.txt hello.sh shared
Output
-rw------- 600 notes.txt
-rwxr-xr-x 755 hello.sh
drwxrwxr-x 775 shared

stat -c '%a' prints the octal form, which is handy in scripts.

Recursive changes use -R, but be careful: you usually want different modes for files and directories. Let find pick them separately:

Terminal
find shared -type d -exec chmod 755 {} +    # directories
find shared -type f -exec chmod 644 {} +    # files

(Or use chmod -R u=rwX,go=rX shared, where a capital X adds execute only to directories and files that are already executable.)

🚫 Never chmod -R 777 to "fix" a permission problem. It makes everything writable by every user and process on the system, a classic security hole. Find out who needs access and grant exactly that.

Ownership: chown and chgrp#

Only root can give a file to another user, so these usually need sudo:

Terminal
sudo chown www-data index.html              # change the owner
sudo chown www-data:www-data index.html     # owner and group
sudo chgrp developers report.txt            # group only (or: chown :developers)
sudo chown -R ada:ada ~/projects            # recursively

A common real-world fix: files created with sudo belong to root, so your user can't edit them. Run sudo chown -R "$USER": path to take them back.

umask: default permissions#

New files start from 666 (files) or 777 (directories), and the umask removes bits from that:

Terminal
umask
touch newfile; mkdir newdir
stat -c '%a %n' newfile newdir
Output
0022
644 newfile
755 newdir

With umask 0022, new files get 644 and new directories 755. A stricter umask 077 (set it in ~/.bashrc) makes new files private (600/700).

Special bits: setuid, setgid and sticky#

Terminal
ls -l /usr/bin/passwd
ls -ld /tmp
Output
-rwsr-xr-x 1 root root 118168 Apr 19  2025 /usr/bin/passwd
drwxrwxrwt 18 root root 4096 Oct  1 10:53 /tmp
  • setuid (s in the user's x position, octal 4000): the program runs with its owner's privileges. passwd is owned by root and setuid, which is how ordinary users can update the root-owned /etc/shadow. setuid programs are powerful, so audit them: find / -perm -4000 -type f 2>/dev/null.
  • setgid (s in the group position, 2000): on a directory, new files inherit the directory's group. That's perfect for shared team folders: chmod 2775 /srv/project.
  • sticky bit (t in the others position, 1000): in a shared writable directory, users can delete only their own files. That's why /tmp is 1777.

Access control lists (ACLs)#

When owner/group/others isn't flexible enough, for example "give one extra user read access", use ACLs (package acl):

Terminal
setfacl -m u:www-data:r notes.txt   # let www-data read it
getfacl notes.txt
setfacl -b notes.txt                # remove all ACL entries
Output
# file: notes.txt
# owner: ada
# group: ada
user::rw-
user:www-data:r--
group::---
mask::r--
other::---

(getfacl was run before setfacl -b, so the extra user:www-data entry is still visible.)

A + at the end of the permission string in ls -l (-rw-r-----+) tells you a file has ACL entries.

Diagnosing "Permission denied"#

  1. Who am I? Run id to see your user and groups.
  2. What does the file allow? ls -l file.
  3. What about every directory on the path? You need x on each one. namei -l /path/to/file shows the permissions along the whole path.
  4. Is it a system file? Use sudo, or better, sudoedit.
  5. Just added to a group? Group membership applies at the next login (or run newgrp groupname).

Common mistakes#

  • chmod -R 777 as a fix-all. It hides the real problem and opens a security hole.
  • Removing x from directories with a careless chmod -R 644 dir. After that nobody can cd into the subdirectories. Use u=rwX,go=rX instead.
  • Editing files as root and leaving them root-owned in your home directory or project, so your editor or app can't write them later.
  • SSH keys that are too open. ssh refuses a private key that others can read. Keep ~/.ssh at 700 and keys at 600.
  • Forgetting the directory's permissions. A file set to 644 is still unreachable if a parent directory lacks x.

What's next#

Permissions are about users and groups. Next you'll create and manage users, groups and sudo access.

Check your understanding

Quick quiz

0/3 answered
  1. 1.What permissions does chmod 640 report.txt set?

  2. 2.What does the execute (x) permission mean on a directory?

  3. 3.Why does /tmp show drwxrwxrwt?

Finished reading?

Mark this lesson complete to track your progress.