File Permissions and Access Control Lists

Spoorti ShettySpoorti Shetty
15 min read

Hey there, fellow Linux enthusiasts! Today, I’m diving into an essential topic: file permissions and ACLs. Understanding these concepts is crucial for managing your system and ensuring that your files are secure and accessible to the right people. Whether you’re a newbie or looking to brush up on your skills, I’ll break it down in a way that’s easy to grasp. Let’s get started!

Understanding File Permissions

In Linux, file permissions might seem a bit intimidating at first, but once you get the hang of it, it’s pretty straightforward.

Run ls -ltr in your directory to get a detailed list of files and directories.

ubuntu@ip-172-31-23-226:~/day6$ ls -ltr
total 8
-rw-rw-r-- 1 user-2 testers       0 Oct 17 12:18 xyz
drwxrwxr-x 2 ubuntu developers 4096 Oct 17 12:18 pqr
-rwxr-xr-- 1 user-1 developers   48 Oct 18 17:41 abc

In this output, let’s consider the detailed list view of the file abc:

-rwxr-xr-- 1 user-1 developers   48 Oct 18 17:41 abc

So, what does this mean? Let’s break it down

  • First character:

    • - indicates it's a regular file.

    • d means it’s a directory.

  • Next three characters (rwx): These are the permissions for the user (owner):

    • r: Read permission (4)

    • w: Write permission (2)

    • x: Execute permission (1)

  • Next three characters (r-x): These show the permissions for the group:

    • r: Read permission (4)

    • -: No write permission (0)

    • x: Execute permission (1)

  • Last three characters (r--): These represent the permissions for others:

    • r: Read permission (4)

    • -: No write permission (0)

    • -: No execute permission (0)

In short, the first character tells you if it’s a file or a directory, while the rest indicates what different users can do with that file.

  • 1 is the number of hard links to the file.

  • user-1 and developers indicate the owner and group of the file.

  • 48 shows the file size in bytes.

  • Oct 18 17:41 indicates the last modification date and time.

  • abc is the name of the file.

Binary Representation of Permissions

Sometimes it helps to visualize permissions in binary format, especially when dealing with numeric (octal) modes. Here’s a quick table to illustrate:

PermissionBinaryNumeric
---0000
--x0011
-w-0102
-wx0113
r--1004
r-x1015
rw-1106
rwx1117

This makes it easier to see how we can combine permissions using numbers. For instance, if you see 755, that translates to full permissions for the user, and read and execute permissions for the group and others.

Numeric (Octal) vs. Symbolic Modes

Now, let’s talk about how to change file permissions. There are two main ways to do this: numeric (octal) mode and symbolic mode.

  1. Numeric Mode:
    You can represent permissions using a three-digit number:

     chmod 755 fileName
    

    This sets:

    • 7 (rwx) for the user

    • 5 (r-x) for the group

    • 5 (r-x) for others

  2. Symbolic Mode:
    You can also specify permissions using letters (u, g, o for user, group, and others):

     chmod u=rwx,g=rx,o=r fileName
    

    This gives full permissions to the user, read and execute to the group, and read-only to others.

Changing Permissions with chmod

The chmod command is your go-to for changing file permissions. Here are some practical examples:

  • Grant full permissions to the user (owner):

    • Symbolic:

        chmod u+rwx fileName
      

      This grants full permissions (read, write, execute) to the user, but it doesn't modify the permissions of the group or others. If group and others already have permissions, they will remain unchanged.

    • Octal:

        chmod 700 fileName
      

      This explicitly sets full permissions for the owner, and ensures that group and others have no permissions at all.

  • Remove write permission for others:

    • Symbolic:

        chmod o-w fileName
      

      This removes write permission for others but leaves the user and group permissions unchanged.

    • Octal:

        chmod 775 fileName
      

      This sets full permissions for the owner and group, and read and execute for others. It explicitly defines all permissions for all categories.

  • Set specific permissions for all categories (read and write for the user, read-only for the group and others):

    • Symbolic:

        chmod u=rw,g=r,o=r fileName
      
    • Octal (equivalent):

        chmod 644 fileName
      

Advanced chmod Usage

  • Recursive Permission Change:
    If you want to change permissions for a directory and all its contents, use:

      chmod -R 755 directoryName
    
  • Make a Script Executable:
    Got a script that needs to run? Make it executable with:

      chmod +x script.sh
    

Understanding Ownership with chown

Every file has an owner and a group, and sometimes you need to change that ownership. Enter the chown command:

  • Change the file owner:

      chown newOwner fileName
    
  • Change both the owner and group:

      chown newOwner:newGroup fileName
    
  • Change only the group ownership of a file:

      chown :newGroup fileName
    
  • Change ownership recursively:

      chown -R newOwner directoryName
    

Common Scenarios to use chown

  • Set file ownership to root:

      sudo chown root fileName
    
  • Transfer file ownership to another user:

      sudo chown anotherUser fileName
    

Default Permissions with umask

What is umask?

The umask command sets the default permissions for new files and directories. When you create a file or directory, Linux starts with a "base" set of permissions and then subtracts the umask value from it to decide the final permissions.

  • Base permissions for directories: 777 (read, write, execute for everyone).

  • Base permissions for files: 666 (read, write for everyone, files usually don't have execute permission by default).

How umask Works

The umask value subtracts permissions from these base settings. It's like saying, "These are the permissions I don't want."

For example:

  • A umask of 022 subtracts write permissions for the group and others.

Understanding with an Example

1. Default Directory Permissions

The base permission for directories is 777 (meaning everyone can read, write, and execute):

Base: 777 (rwxrwxrwx)
Umask: 022 (--w--w--)
Result: 755 (rwxr-xr-x)

So, when you set umask to 022, new directories will have 755 permissions:

  • The owner can read, write, and execute.

  • The group and others can only read and execute (no write permission).

2. Default File Permissions

The base permission for files is 666 (meaning everyone can read and write):

Base: 666 (rw-rw-rw-)
Umask: 022 (--w--w--)
Result: 644 (rw-r--r--)

When you create a new file with a umask of 022, it will have 644 permissions:

  • The owner can read and write.

  • The group and others can only read (no write permission).

Viewing and Setting umask

  1. Check the current umask value:

     umask
    
  2. Set a new umask value:

     umask 022
    

This tells Linux to subtract 022 from the base permissions when creating new files or directories, so they are created with more restrictive access.

Access Control Lists (ACLs)

As powerful as standard permissions are, sometimes they aren’t flexible enough for more complex scenarios, like assigning different permissions to multiple users on the same file. That's where Access Control Lists (ACLs) come into play.

ACLs allow you to set detailed permissions for specific users or groups beyond the traditional owner/group/others structure.

Viewing ACLs

To see the current ACLs on a file or directory, you can use the getfacl command:

getfacl filename

This will display the current permissions, including any ACLs that have been set.

Setting ACLs

To assign ACLs, you’ll use the setfacl command. For example, if you want to give a specific user (let’s say "user3") read permission on a file, you can run:

setfacl -m u:user3:r filename
  • -m: Modify the ACL.

  • u:user3:r: Assigns read permission to user3.

You can also set ACLs for groups:

setfacl -m g:group1:rw filename

This command gives group1 read and write access to the file.

Example usage (setting ACLs for the file ‘abc’):

ubuntu@ip-172-31-23-226:~/day6$ sudo setfacl -m u:user-3:r abc
ubuntu@ip-172-31-23-226:~/day6$ sudo setfacl -m g:testers:rw abc 
ubuntu@ip-172-31-23-226:~/day6$ getfacl abc
# file: abc
# owner: user-1
# group: developers
user::rwx
user:user-3:r--
group::r-x
group:testers:rw-
mask::rwx
other::r--

Default ACLs for Directories

ACLs can also be applied to directories, and you can specify default ACLs, which will be inherited by any files created within the directory:

setfacl -d -m u:user3:rw directoryname

The -d flag sets a default ACL. Any new files created in the directory will automatically inherit these permissions.

Task: Create a directory and set specific ACL permissions for different users and groups. Verify the permissions using getfacl.

Steps Involved:

  1. Create a Directory: Create a new directory where ACL permissions will be set.

  2. Set ACL Permissions: Assign different permissions to multiple users and groups using the setfacl command.

  3. Verify ACL Permissions: Use the getfacl command to check and verify the assigned ACL permissions.

Let’s get started!

1. Create a Directory

First, let's create a directory named project_directory.

mkdir project_directory

2. Set Specific ACL Permissions for Different Users and Groups

Now, we'll assign different ACL permissions for two users (alice and bob) and a group (developers).

  • Assign read and execute permissions to the user alice.

  • Assign read, write, and execute permissions to the user bob.

  • Assign read-only permissions to the group developers.

Commands to Set ACL Permissions:

# Give 'alice' read and execute permissions
setfacl -m u:alice:rx project_directory

# Give 'bob' full read, write, and execute permissions
setfacl -m u:bob:rwx project_directory

# Give the group 'developers' read-only permissions
setfacl -m g:developers:r project_directory

3. Verify the Permissions Using getfacl

To confirm that the permissions have been applied correctly, use the getfacl command:

getfacl project_directory

This command will display the ACLs for the directory. The output should show the default and additional ACLs for the specified users and group.

Sample Output of getfacl:

ubuntu@ip-172-31-23-226:~/day6$ getfacl project_directory
# file: project_directory
# owner: ubuntu
# group: ubuntu
user::rwx
user:alice:r-x
user:bob:rwx
group::rwx
group:developers:r--
mask::rwx
other::r-x
  • user::rwx: The owner has full permissions (read, write, execute).

  • user:alice:r-x: User alice has read and execute permissions.

  • user:bob:rwx: User bob has full permissions (read, write, execute).

  • group::rwx: Group has full permissions (read, write, execute).

  • group:developers:r--: The group developers has read-only permission.

  • other::r-x: Other users have read and execute permissions.

In this task, we created a directory and set ACL permissions for different users (alice and bob) and a group (developers). We assigned different levels of access, including read-only, read and execute, and full permissions. Finally, we verified the ACL settings using the getfacl command. This approach provides detailed control over access to the directory, extending the traditional permission system in Linux.

Task: Create a script that changes the permissions of multiple files in a directory based on user input.

When managing a directory with multiple files, you might want to change the permissions for all files in that directory. This can be automated by writing a shell script that takes user input and applies the permission changes accordingly.

The script will:

  1. Prompt the user for the directory path.

  2. Ask for the permissions in numeric format (e.g., 755, 644).

  3. Apply those permissions to all files in the directory.

The Script

#!/bin/bash

# Ask the user for the directory path
read -p "Enter the directory path: " dir_path

# Check if the directory exists
if [ ! -d "$dir_path" ]; then
    echo "The directory $dir_path does not exist."
    exit 1
fi

# Ask the user for the desired permissions in numeric format
read -p "Enter the permissions you want to set (e.g., 755, 644): " permissions

# Validate the permissions input (must be a 3- or 4-digit number)
if [[ ! $permissions =~ ^[0-7]{3,4}$ ]]; then
    echo "Invalid permission format. Please enter a valid 3- or 4-digit permission number."
    exit 1
fi

# Apply the permissions to all files in the directory
for file in "$dir_path"/*; do
    if [ -f "$file" ]; then
        sudo chmod "$permissions" "$file"
        echo "Changed permissions of $file to $permissions"
    fi
done

echo "Permissions updated for all files in $dir_path."

How It Works:

  1. User Input: The script first prompts the user for the directory path and the desired permissions.

  2. Validation: It checks whether the directory exists and whether the permissions input is valid (using a regular expression that matches numeric values like 755 or 0644).

  3. Permission Change: If the input is valid, the script uses a for loop to apply the permissions to each file in the directory using the chmod command.

  4. Output: The script prints a confirmation message for each file whose permissions are changed.

Usage Example:

 $ ./change_permissions.sh
Enter the directory path: /home/user/docs
Enter the permissions you want to set (e.g., 755, 644): 644
Changed permissions of /home/user/docs/file1.txt to 644
Changed permissions of /home/user/docs/file2.txt to 644
Permissions updated for all files in /home/user/docs.

Task: Write a script that sets ACL permissions for a user on a given file, based on user input.

The script will:

  1. Prompt the user for the file path.

  2. Ask for the username for whom to set the ACL permissions.

  3. Prompt for the permissions (read, write, execute).

  4. Apply the ACL permissions using the setfacl command.

The Script

#!/bin/bash

# Prompt the user for the file path
read -p "Enter the file path: " file_path

# Check if the file exists
if [ ! -f "$file_path" ]; then
    echo "The file $file_path does not exist."
    exit 1
fi

# Prompt for the username
read -p "Enter the username to set ACL for: " username

# Check if the user exists in the system
if ! id "$username" &>/dev/null; then
    echo "The user $username does not exist."
    exit 1
fi

# Prompt for the permissions (read, write, execute)
read -p "Enter the permissions you want to set (r, w, x or a combination, e.g., rwx): " permissions

# Validate the permissions input
if [[ ! $permissions =~ ^[rwx-]+$ ]]; then
    echo "Invalid permissions. Please enter a combination of r, w, and x."
    exit 1
fi

# Apply the ACL permissions using setfacl
setfacl -m u:"$username":"$permissions" "$file_path"

# Check if the ACL command was successful
if [ $? -eq 0 ]; then
    echo "ACL permissions set successfully for user $username on file $file_path."
else
    echo "Failed to set ACL permissions."
fi

# Display the ACL permissions for the file
getfacl "$file_path"

How It Works:

  1. User Input: The script prompts for the file path, username, and permissions (read, write, execute) for setting ACL.

  2. Validation: It checks whether the file and user exist, and validates the permissions input to ensure it only includes valid characters (r, w, x).

  3. Set ACL Permissions: The script uses the setfacl command to apply the specified permissions for the user on the given file.

  4. Output: It confirms the success of the operation and displays the ACL permissions for the file using the getfacl command.

Usage Example:

$ ./set_acl_permissions.sh
Enter the file path: /home/user/docs/file1.txt
Enter the username to set ACL for: john
Enter the permissions you want to set (r, w, x or a combination, e.g., rwx): rw
ACL permissions set successfully for user john on file /home/user/docs/file1.txt.
# file: home/user/docs/file1.txt
# owner: user
# group: user
user::rw-
user:john:rw-
group::r--
mask::rw-
other::r--

In this example:

  • The script sets read and write (rw) permissions for the user john on the file /home/user/docs/file1.txt.

  • After setting the ACL, the updated permissions are displayed.

Advanced Permission Management: Sticky Bit, SUID, and SGID

While file permissions and ACLs give you a lot of control, sometimes you need even more granular permissions for specific use cases. Enter the Sticky Bit, Setuid (SUID), and Setgid (SGID).

Sticky Bit

The sticky bit is most commonly used on shared directories (like /tmp), where multiple users can create files. It ensures that only the file owner can delete or modify their files, even if other users have write access to the directory.

To set the sticky bit on a directory:

chmod +t directoryname

You can verify the sticky bit is set by running ls -l. The output will show a t in the final position of the permissions string, like this:

drwxrwxrwt

SUID (Set User ID)

When the SUID bit is set on an executable file, any user who runs that file will have the file owner’s privileges during execution. This is commonly used for commands like passwd, which needs root privileges but can be run by any user.

To set the SUID bit:

chmod u+s filename

You’ll see an s in the user permission field if SUID is set:

-rwsr-xr-x

SGID (Set Group ID)

The SGID bit can be set on files and directories. On files, it works similarly to SUID, but with group privileges. On directories, it ensures that new files created within the directory inherit the group ownership of the directory rather than the creating user's primary group.

To set SGID:

chmod g+s directoryname

You’ll see an s in the group permission field if SGID is set:

drwxr-sr-x

Backup and Restore Permissions

Managing permissions across multiple files can be tricky, especially when you need to maintain consistency across a directory structure. That’s why it’s useful to be able to back up and restore file permissions.

Backing Up Permissions

To create a backup of the current permissions, you can use the getfacl command to save them to a file:

getfacl -R directoryname > permissions_backup.txt

This will recursively save all ACLs and regular permissions for files within the specified directory.

Let’s write a script to backup permissions using this command:

#!/bin/bash

# Backup permissions (including ACLs) for a specified directory

# Check if directory argument is provided
if [ $# -ne 1 ]; then
    echo "The script should be executed like this: $0 <directory>"
    exit 1
fi

DIR=$1
BACKUP_FILE="permissions_backup.txt"

# Backup permissions
getfacl -R "$DIR" > "$BACKUP_FILE"

if [ $? -eq 0 ]; then
    echo "Backup successful: Permissions saved to $BACKUP_FILE"
else
    echo "Error: Failed to backup permissions."
fi

Sample Output for Backup:

$ ./backup_permissions_acl.sh /mydir
Backup successful: Permissions saved to permissions_backup.txt

Restoring Permissions

Once you’ve backed up your permissions, restoring them is simple with setfacl. Use the following command to apply the saved permissions:

setfacl --restore=permissions_backup.txt

This ensures that all your file and directory permissions are restored to their previous state.

Let’ write a script to restore permissions using this command:

#!/bin/bash

# Restore permissions (including ACLs) from a backup file

# Check if backup file argument is provided
if [ $# -ne 1 ]; then
    echo "The script should be executed like this: $0 <backup-file>"
    exit 1
fi

BACKUP_FILE=$1

# Restore permissions
setfacl --restore="$BACKUP_FILE"

if [ $? -eq 0 ]; then
    echo "Restore successful: Permissions restored from $BACKUP_FILE"
else
    echo "Error: Failed to restore permissions."
fi

Sample Output for Restore:

$ ./restore_permissions_acl.sh permissions_backup.txt
Restore successful: Permissions restored from permissions_backup.txt

Conclusion

File permissions, ownership, and ACLs form the backbone of security in Linux. By mastering these concepts, along with special permissions like the sticky bit, SUID, and SGID, you can gain fine-grained control over your system. Plus, the ability to back up and restore permissions ensures you can easily maintain a secure, well-organized environment. Keep experimenting, and you’ll soon be managing your Linux system like a pro!

0
Subscribe to my newsletter

Read articles from Spoorti Shetty directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Spoorti Shetty
Spoorti Shetty