The Ultimate Guide to Linux File Permissions: chmod and chown Demystified

The CyberSec Guru

Updated on:

Ultimate Guide to Linux File Permissions

If you like this post, then please share it:

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Why your support matters: Zero paywalls: Keep the content 100% free for learners worldwide, Writeup Access: Get complete writeup access within 12 hours of machine drop along with scripts and commands.

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

You’ve done it. You’ve downloaded a script, you try to run it, and you get that dreaded message: bash: ./myscript.sh: Permission denied.

Or maybe you’re trying to lock down a sensitive file, like a private key, and SSH still complains that your “permissions are too open.”

Sound familiar?

Welcome to the world of Linux file permissions. It’s the single most fundamental—and often most confusing—part of the Linux operating system. It’s the digital bouncer that decides who gets into the club, who gets the VIP section, and who can’t even look at the building.

But here’s the good news: it’s not as complicated as it looks.

By the end of this guide, you will be an absolute master of file permissions. You won’t just know what chmod 755 means; you’ll understand why you’re using it, how it works at a binary level, and how to wield it to secure any Linux system.

This is not a quick overview. This is the definitive, “no external info required” guide. Let’s dive in.

The “Why, What, and Who” of Linux Permissions

Before we type a single command, we need to understand the three core concepts:

  1. The “What”: The three permissions (Read, Write, Execute).
  2. The “Who”: The three permission groups (User, Group, Others).
  3. The “How”: The commands to change them (chmod, chown).

The “What”: Read, Write, and Execute (RWX)

In Linux, everything is a file. A text document is a file. A directory is just a special type of file. An image is a file. A running program is a file.

And for every single file, there are three basic permissions you can grant or deny.

  • Read (r): The ability to open and view the contents of a file.
  • Write (w): The ability to modify, change, or delete the contents of a file.
  • Execute (x): The ability to run the file as a program or script.

This seems simple, but there’s a critical difference between how these permissions apply to files versus directories. This is where 90% of beginners get stuck.

Permissions for a FILE (e.g., report.txt):

  • Read (r): You can open the file and read its text (e.g., using cat, less, nano).
  • Write (w): You can edit the file and save your changes. You can also delete the file (though this is also controlled by the directory’s permissions).
  • Execute (x): You can run the file as a program (e.g., ./myscript.sh). This permission is useless for a text file or image but essential for scripts and applications.

Permissions for a DIRECTORY (e.g., ~/Documents):

  • Read (r): You can list the contents of the directory (i.e., you can use the ls command to see what files are inside).
    • Gotcha: If you have x but not r, you can cd into the directory, but ls will give you a “Permission denied” error. You’re in the room, but you’re blindfolded.
  • Write (w): You can modify the contents of the directory. This means you can create new files, delete files, and rename fileswithin that directory.
    • Critical Gotcha: You need w on the directory to delete a file, not necessarily on the file itself!
  • Execute (x): You can enter the directory (i.e., you can use the cd command to make it your working directory).
    • Gotcha: If you have r and w but not x, you can’t cd into the directory. You can see who’s in the club, but you can’t get past the bouncer. x is the “pass-through” or “enter” permission for directories.
File vs Directory Permission
File vs Directory Permission

The “Who”: User, Group, and Others (UGO)

Now that we know what can be done, we need to know who can do it. Linux security is built on a “UGO” model. Every file and directory has three “owners.”

  • User (u): This is the Owner of the file. By default, the person who creates the file is its owner. They have the most control.
  • Group (g): This is the Group that owns the file. Think of this as a team or a department. You can give permissions to your “Group” (e.g., “developers”) that are different from what everyone else gets.
  • Others (o): This is everyone else. Any user on the system who is not the owner and does not belong to the group.

This UGO model is simple but powerful. It lets you create complex rules:

  • “I (User) can read and write this file.”
  • “My team (Group) can only read this file.”
  • “Everyone else (Others) can’t even see this file.”

How to Read Permissions

You’ve probably typed ls -l before and seen a wall of confusing text. Let’s finally, and permanently, demystify it.

When you run ls -l, you get output that looks like this:

drwxr-xr-x 2 alice staff 4096 Nov 13 10:30 Public -rw-r--r-- 1 alice staff 312 Nov 13 09:15 config.ini -rwxr-xr-x 1 alice staff 89 Nov 13 09:20 run_report.sh -rw------- 1 alice staff 1638 Nov 13 09:25 id_rsa

Let’s break down that first column. It’s a 10-character string.

Character 1: File Type This first character tells you what you’re looking at.

  • - : A regular file.
  • d : A directory.
  • l : A symbolic link (a shortcut to another file).
  • (There are others, like c for character device, but -, d, and l are the 99%.)

Characters 2-10: The Permission Triplets (UGO) These next nine characters are the most important part. They are three sets of three characters, one set for each of our “Who’s” (User, Group, Others).

Each triplet follows the same rwx order. If the permission is not granted, you see a dash (-).

Let’s take -rwxr-xr-- from our example:

  • rwx (Triplet 1: User): The owner (alice) can read, write, and execute this file.
  • r-x (Triplet 2: Group): Members of the staff group can read and execute, but cannot write to the file.
  • r-- (Triplet 3: Others): Everyone else on the system can read the file, but cannot write or execute it.

Putting It All Together (Full Line Breakdown): drwxr-xr-x 2 alice staff 4096 Nov 13 10:30 Public

  • d – It’s a directory.
  • rwx – The owner (alice) can read, write, and execute (list, modify, and cd into it).
  • r-x – The staff group can read and execute (list and cd into it, but not create/delete files).
  • r-x – Others can also read and execute (list and cd into it).
  • 2 – Link count (for directories, number of items inside + . and ..).
  • alice – The User (Owner).
  • staff – The Group.
  • 4096 – File size in bytes.
  • Nov 13 10:30 – Last modification timestamp.
  • Public – The name of the directory.

That’s it! You can now read the language of Linux permissions.

Changing Permissions with chmod

Now we get to the action. The chmod (change mode) command is your tool for changing these permissions.

There are two ways to use chmod: the Symbolic method (easy and readable) and the Numeric (Octal) method (fast and powerful). You need to know both.

Method 1: The Symbolic (Text) Method

The symbolic method is descriptive. You tell chmod who you’re changing, what you’re doing, and which permission you’re changing.

The formula is: chmod [who][operator][permission] <file>

  • Who? (The “UGO” part):
    • u – User (Owner)
    • g – Group
    • o – Others
    • a – All (User, Group, and Others)
  • Operator? (What to do):
    • +Add a permission
    • -Remove a permission
    • =Set a permission exactly (and remove all others for that “who”)
  • Permission? (The “RWX” part):
    • r – Read
    • w – Write
    • x – Execute

Practical Examples:

  1. “My script won’t run!” (Permission Denied) You need to add the execute permission for the user.# Before: -rw-r--r-- chmod u+x myscript.sh # After: -rwxr--r--
  2. “I want my team to be able to edit this file.” You need to add the write permission for the group.# Before: -rw-r--r-- chmod g+w shared_doc.txt # After: -rw-rw-r--
  3. “This file is too public. I want to remove all permissions for ‘Others’.” You need to set the permissions for others to nothing.# Before: -rw-rw-r-- chmod o= shared_doc.txt # After: -rw-rw----
  4. “I want to make a file read-only for everyone (including myself).” You need to remove the write permission for all.# Before: -rw-rw-r-- chmod a-w shared_doc.txt # After: -r--r--r--
  5. “I want to add r and w for the User, but only r for Group and Others.” You can combine commands with a comma (no spaces!).chmod u=rw,go=r config.file # After: -rw-r--r--

What about directories? The Recursive -R Flag

If you want to apply permissions to a directory and everything inside it, you need the recursive flag: -R.

Warning: Be extremely careful with chmod -R. You can accidentally make every file in a directory executable, or worse, remove your own read permissions from everything.

Example: “I want to make my entire ‘project’ folder readable by my group.”

chmod -R g+r ~/project

This adds the r permission to ~/project, ~/project/file1.txt, ~/project/src/main.py, etc.

Method 2: The Numeric (Octal) Method (The “Pro” Way)

This is the method you see everywhere. chmod 755, chmod 644, chmod 600. It looks like magic, but it’s just simple math.

Remember our three permissions? r, w, and x. In the binary world, we can represent them as “on” or “off” (1 or 0).

We assign a numeric value to each one:

  • r (Read) = 4 (binary 100)
  • w (Write) = 2 (binary 010)
  • x (Execute) = 1 (binary 001)

To get the permission value for a “Who” (U, G, or O), you just add the numbers together.

  • --- = 0 + 0 + 0 = 0 (No permissions)
  • --x = 0 + 0 + 1 = 1 (Execute only)
  • -w- = 0 + 2 + 0 = 2 (Write only)
  • -wx = 0 + 2 + 1 = 3 (Write and execute)
  • r-- = 4 + 0 + 0 = 4 (Read only)
  • r-x = 4 + 0 + 1 = 5 (Read and execute)
  • rw- = 4 + 2 + 0 = 6 (Read and write)
  • rwx = 4 + 2 + 1 = 7 (Read, write, and execute)
Octal Permission Table
Octal Permission Table

The chmod command then uses three of these numbers back-to-back: chmod [User][Group][Others] <file>

So, when you type chmod 755 script.sh, you are setting:

  • User: 7 (rwx) – Owner can read, write, and execute.
  • Group: 5 (r-x) – Group can read and execute (but not write).
  • Others: 5 (r-x) – Others can read and execute (but not write).
  • Full ls -l output: -rwxr-xr-x

The 3 Most Common Permissions You MUST Know

This numeric system is why you see the same numbers over and over. Here are the “big three” and why they are so common.

1. chmod 644 (The “Public File”)

  • User: 6 (rw-) – Owner can read and write.
  • Group: 4 (r--) – Group can only read.
  • Others: 4 (r--) – Others can only read.
  • Full ls -l output: -rw-r--r--
  • When to use it: This is the default for most files (text files, images, documents). It’s perfect for files on a web server that people need to see but not change or run.

2. chmod 755 (The “Public Script/Directory”)

  • User: 7 (rwx) – Owner can read, write, and execute.
  • Group: 5 (r-x) – Group can read and execute.
  • Others: 5 (r-x) – Others can read and execute.
  • Full ls -l output: -rwxr-xr-x
  • When to use it: This is the standard for executables and directories.
    • For scripts: Everyone can run it, but only you can change it.
    • For directories: Everyone can cd into it and list its contents, but only you can create or delete files inside it. This is the default for your /home folder, for example.

3. chmod 600 (The “Fort Knox”)

  • User: 6 (rw-) – Owner can read and write.
  • Group: 0 (---) – Group has no permissions.
  • Others: 0 (---) – Others have no permissions.
  • Full ls -l output: -rw-------
  • When to use it: This is for highly sensitive, private files. The classic example is your SSH private key (~/.ssh/id_rsa). In fact, SSH will refuse to work if your key file’s permissions are any more open than 600!

One more common one: chmod 700 (rwx------). This is the “Fort Knox” for a directory. It creates a completely private folder that only you can enter, list, or modify.

Special Permissions (suid, sgid, sticky)

This is the part that separates the pros from the amateurs. If you really want to rank #1, you need to understand the “special” permissions.

This involves adding a fourth numeric digit to the front of your chmod command (e.g., chmod 4755).

This fourth digit handles three special flags:

  • setuid (4): “Set User ID”
  • setgid (2): “Set Group ID”
  • sticky bit (1): “Sticky Bit”

You add them up just like RWX: chmod [Special][User][Group][Others]

1. The setuid Bit (Value: 4)

  • Command: chmod 4755 /usr/bin/passwd
  • What it does: When an executable file with setuid is run, it executes with the permissions of the file’s owner, not the user who ran it.
  • How ls -l shows it: The user’s x becomes an s. (-rwsr-xr-x)
  • The Classic Example: The passwd command, which lets you change your password.
    • The file /etc/shadow (where your encrypted password lives) is owned by root and has 600 permissions. You can’t write to it.
    • The command /usr/bin/passwd is also owned by root, but it has the setuid bit set.
    • When you (a normal user) run passwd, Linux sees the setuid bit and says, “Aha! I’m going to run this command as if root were running it.”
    • This temporarily elevates the command’s privileges, allowing it to write your new password to the root-owned /etc/shadow file.
  • Security Risk: This is incredibly powerful and dangerous. Never set setuid on your own scripts unless you are 100% sure they are secure.

2. The setgid Bit (Value: 2)

  • Command: chmod 2775 /var/www/shared_project
  • What it does: It has two effects:
    1. On a file: The executable runs with the permissions of the file’s group (less common).
    2. On a directory: This is the super useful one. Any new file or directory created inside this directory will automatically have its group set to this directory’s group, not the user’s primary group.
  • How ls -l shows it: The group’s x becomes an s. (drwxr-sr-x)
  • The Classic Example: A shared folder for a web server.
    • You have a directory /var/www/shared_project owned by alice:developers.
    • You set chmod 2775 on it.
    • When user bob (who is also in the developers group) creates a new file index.html inside it, that file will be automatically owned by bob:developers (instead of bob:bob).
    • This is essential for collaboration, as it ensures everyone on the team can still edit new files.

3. The sticky Bit (Value: 1)

  • Command: chmod 1777 /tmp
  • What it does: When set on a directory, it adds a special rule: A user can only delete or rename files that they personally own, even if the directory gives them w (write) permissions.
  • How ls -l shows it: The other’s x becomes a t. (drwxrwxrwt)
  • The Classic Example: The /tmp directory.
    • /tmp has 777 permissions, meaning everyone (User, Group, Others) can read, write, and execute.
    • This means any user can create files in /tmp.
    • But with w permission, shouldn’t that mean any user can also delete any file?
    • The sticky bit (1) prevents this. It says, “Sure, everyone can write, but you can only delete your own stuff.” This stops a malicious user from deleting another user’s temporary files.
Sticky Bit (t) in Unix File Permissions
Sticky Bit (t) in Unix File Permissions

Changing the “Who”: Mastering chown and chgrp

chmod changes the permissions (the “What”). chown changes the owner (the “Who”).

The chown (change owner) command is simple but requires sudo (root privileges), as you can’t just give your files away to someone else.

Common chown Syntax:

  1. Change the Owner (User) only:sudo chown new_owner filename.txt
  2. Change the Owner and the Group: This is the most common use. Use a colon (:) to separate them.# Syntax: sudo chown user:group filename.txt sudo chown alice:developers report.pdf
  3. Change the Group only: You can do this by putting nothing before the colon.# Syntax: sudo chown :group filename.txt sudo chown :staff important_file.log

The chgrp command: There is also a separate chgrp (change group) command, but chown is more common since it can do both.

sudo chgrp staff important_file.log

The chown Recursive -R Flag Just like chmod, chown has a -R flag that is mission-critical for working with directories.

The Classic Web Server Example: Imagine you just uploaded your website files to /var/www/html. They are probably owned by root:root, which is bad. The web server (e.g., nginx or apache) runs as a special user, like www-data. You need to give that user ownership.

# Give ownership of *everything* inside /var/www/html
# to the www-data user and www-data group.
sudo chown -R www-data:www-data /var/www/html

This single command is one of the most common and powerful uses of chown.

Setting the Defaults: Understanding umask

You’re almost there. This is the last piece of the puzzle.

Have you ever wondered why new files are created with 644 (-rw-r--r--) and new directories with 755 (drwxr-xr-x)?

The answer is umask (user mask).

umask is a filter. It’s the “default permissions to remove.”

  • The maximum possible permission for a new directory is 777 (rwxrwxrwx).
  • The maximum possible permission for a new file is 666 (rw-rw-rw-). (Linux wisely never grants x by default, for security).

Your system’s umask is a three-digit number that gets subtracted from these maximums.

The most common umask is 022.

Let’s do the math:

  • New Directory: 777 (max) – 022 (umask) = 755 (rwxr-xr-x)
  • New File: 666 (max) – 022 (umask) = 644 (rw-r--r--)

And just like that, you understand where the defaults come from.

  • You can view your current umask by just typing:umask # Output: 0022 (The first 0 is for the special permissions, which are 0 by default).
  • You can set a new umask for your current terminal session:# Set a more secure umask, which removes group/other write perms (022) # and also removes group/other read perms (027) umask 027 With a umask of 027:
    • New Dir: 777 - 027 = 750 (rwxr-x---)
    • New File: 666 - 027 = 640 (rw-r-----) This is a great umask for a security-conscious environment.

A Final Practical OVERVIEW

Let’s put it all together.

  1. Create a private script.cd ~ touch my_secret_script.sh echo 'echo "This is my secret"' > my_secret_script.sh ls -l my_secret_script.sh # Output: -rw-r--r-- 1 user user 22 Nov 13 11:00 my_secret_script.sh Problem: Everyone can read it (r--), but I can’t run it (rw-).
  2. Fix permissions. Let’s make it private and executable.chmod 700 my_secret_script.sh ls -l my_secret_script.sh # Output: -rwx------ 1 user user 22 Nov 13 11:00 my_secret_script.sh Perfect. Now only I can read, write, and execute it.
  3. Run it../my_secret_script.sh # Output: This is my secret It works!
  4. Create a shared project.sudo mkdir /opt/shared_project sudo chown user:developers /opt/shared_project ls -ld /opt/shared_project # Output: drwxr-xr-x 2 user developers 4096 Nov 13 11:02 /opt/shared_project Problem: My teammate bob (in the developers group) can cd in (r-x) but can’t create files (w).
  5. Fix permissions for collaboration. Let’s allow the group to write, and set the setgid bit so all new files are owned by the developers group.# Add 'w' for the group, and add the 'setgid' (2000) bit sudo chmod 2775 /opt/shared_project ls -ld /opt/shared_project # Output: drwxrwsr-x 2 user developers 4096 Nov 13 11:03 /opt/shared_project Perfect. Now, any developer can create files, and those new files will automatically be owned by the developers group, allowing true collaboration.

You Are Now a Permissions Master

You made it. You now know more about Linux file permissions than 95% of Linux users.

You’re no longer just blindly copying chmod 755 from a Stack Overflow post. You know why.

Let’s recap what you’ve mastered:

  • The “What”: Read, Write, Execute (and what they really mean for files vs. directories).
  • The “Who”: User, Group, Others.
  • How to Read: How to look at ls -l and instantly know what’s going on.
  • How to Change (Symbolic): chmod u+x, chmod g-w, chmod o=r.
  • How to Change (Numeric): chmod 644 (files), chmod 755 (scripts/dirs), chmod 600 (private keys).
  • The “Secret” Level: setuid (4), setgid (2), and the sticky bit (1) for advanced control.
  • How to Change Owners: chown user:group and the all-powerful -R flag.
  • The “Defaults”: umask and how 777 - 022 = 755.

You haven’t just learned a command. You’ve learned a core concept of system security. Go forth and secure your files.

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Your contribution powers free tutorials, hands-on labs, and security resources.

Why your support matters:
  • Writeup Access: Get complete writeup access within 24 hours
  • Zero paywalls: Keep the content 100% free for learners worldwide

Perks for one-time supporters:
☕️ $5: Shoutout in Buy Me a Coffee
🛡️ $8: Fast-track Access to Live Webinars
💻 $10: Vote on future tutorial topics + exclusive AMA access

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

If you like this post, then please share it:

Linux 101

Discover more from The CyberSec Guru

Subscribe to get the latest posts sent to your email!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from The CyberSec Guru

Subscribe now to keep reading and get access to the full archive.

Continue reading