Linux8 min read

Linux file permissions explained

linuxpermissionssecuritybasics

Permissions are the first line of defense on any Linux system. Every file and directory has an owner, a group, and a set of permissions that control who can read, write, or execute it. Getting this wrong means either locking yourself out or letting anyone poke around your stuff.

The basics

Run ls -l and you’ll see something like this:

-rw-r--r-- 1 upi developers 4096 Mar 12 10:30 config.yaml

That first column is the permission string. Break it down:

  • - — file type (- for file, d for directory, l for symlink)
  • rw- — owner permissions (read, write, no execute)
  • r-- — group permissions (read only)
  • r-- — everyone else (read only)

Each position is a bit: read (4), write (2), execute (1). Add them up to get the numeric mode.

chmod: changing permissions

Numeric mode is the shorthand most people use:

chmod 644 config.yaml   # rw-r--r--
chmod 755 deploy.sh     # rwxr-xr-x
chmod 600 id_rsa        # rw-------

The three digits map to owner, group, and others. So 755 means the owner can read/write/execute (7), and everyone else can read/execute (5).

Symbolic mode is more explicit:

chmod u+x deploy.sh     # add execute for owner
chmod go-w config.yaml  # remove write for group and others
chmod a+r readme.txt    # add read for everyone

Use whichever you find clearer. I usually use numeric for setting exact modes and symbolic for tweaking one bit.

Directories need execute

A common gotcha: on a directory, execute permission means “can enter this directory.” Without it, you can’t cd into it or access files inside, even if you know the filenames.

chmod 755 /home/upi/projects  # must have +x to traverse

Read without execute on a directory lets you list filenames but not access them. Execute without read lets you access files if you know their names but not list the directory.

chown and chgrp

chown changes file ownership. chgrp changes the group.

chown upi:developers config.yaml
chown -R upi:developers /opt/app/  # recursive
chgrp developers /opt/app/logs/

Only root can change file ownership. Any user can change the group of files they own, but only to groups they belong to.

The sticky bit

On shared directories like /tmp, you’ll see a t at the end:

drwxrwxrwt 10 root root 4096 Mar 12 10:30 /tmp

The sticky bit means users can only delete their own files in that directory, even if the directory is world-writable. Set it with:

chmod +t /shared/uploads
# or numerically: chmod 1777 /shared/uploads

setuid and setgid

setuid (4) makes a file execute as its owner. setgid (2) makes it execute as the group, or on a directory, makes new files inherit the directory’s group.

chmod 4755 /usr/bin/passwd    # setuid — runs as root
chmod 2775 /opt/team/shared/  # setgid — new files get the team group

The passwd command needs setuid because it has to write to /etc/shadow, which only root can access. This is one of the few legitimate uses of setuid. Be cautious with it otherwise.

umask: default permissions

New files get their permissions from the umask. The default umask is usually 022, which means files are created with 644 (666 - 022) and directories with 755 (777 - 022).

Check your current umask:

umask

Set it for the current session:

umask 027  # files: 640, directories: 750

For a shared system where you want stricter defaults, put umask 027 in /etc/profile or ~/.bashrc.

Common mistakes

Setting 777 on everything. It fixes permission errors fast because it gives everyone full access. It also means any user on the system can read, modify, or delete the files. Don’t do this. Figure out who needs access and grant it specifically.

Forgetting -R on recursive operations. chown upi /opt/app changes the top directory but not the files inside. Use -R when you mean the whole tree.

Confusing file and directory execute. chmod 644 on a directory means nobody can enter it. Directories almost always need execute.

Remarks

Permissions are simple once the model clicks: owner/group/others, read/write/execute. The numeric shorthand becomes second nature after a few uses. Start restrictive (600 for private files, 755 for scripts) and open up only what you need. When something says “Permission denied,” ls -l tells you why.

Related Posts