Skip to content
Search RunEntLinux

Searches general documentation on RunEntLinux. Each distribution has its own documentation search.

    Browse this documentation

    File Permissions and ACLs

    Applies to CentOS Stream 9 & 10 / AlmaLinux 9.x & 10.x / Rocky Linux 9.x & 10.x

    Linux file permissions are the cornerstone of system security. Every file and directory has a set of permission rules that control who can read, write, and execute them. When basic permissions are insufficient, ACLs (Access Control Lists) provide finer-grained control.

    • Understand the rwx permission model
    • Use chmod to modify permissions (symbolic and octal modes)
    • Use chown and chgrp to change ownership and group
    • SUID, SGID, and Sticky Bit special permissions
    • Use ACLs for fine-grained permission control
    • Understand and configure umask
    • A system with EL 9.x or 10.x installed (the commands here work on both)
    • A user account with sudo privileges
    • Familiarity with the basics of User and Group Management
    View file permission details
    $ ls -l /etc/nginx/nginx.conf
    -rw-r--r--. 1 root root 2488 Mar 24 10:00 /etc/nginx/nginx.conf

    Breakdown of the output:

    -rw-r--r--. 1 root root 2488 Mar 24 10:00 nginx.conf
    │├──┤├──┤├──┤ │ │ │ │ │ │
    │ │ │ │ │ │ │ │ │ └─ Filename
    │ │ │ │ │ │ │ │ └─ Modification time
    │ │ │ │ │ │ │ └─ File size
    │ │ │ │ │ │ └─ Group
    │ │ │ │ │ └─ Owner
    │ │ │ │ └─ Hard link count
    │ │ │ └─ Other users' permissions (other)
    │ │ └─ Group permissions (group)
    │ └─ Owner permissions (owner)
    └─ File type (- regular file, d directory, l symbolic link)
    PermissionCharacterMeaning for FilesMeaning for Directories
    ReadrRead file contentsList directory contents
    WritewModify file contentsCreate/delete files in the directory
    ExecutexExecute the file (script/program)Enter the directory (cd)

    Symbolic mode uses u (owner), g (group), o (other), a (all) combined with + (add), - (remove), = (set) to modify permissions.

    Add execute permission for the owner
    $ chmod u+x script.sh
    Remove write permission for others
    $ chmod o-w file.txt
    Add read and write permissions for the group
    $ chmod g+rw shared.doc
    Set owner to rwx, group and others to read-only
    $ chmod u=rwx,g=r,o=r script.sh
    Add execute permission for all users
    $ chmod a+x script.sh

    Each permission bit corresponds to a numeric value:

    PermissionValue
    r4
    w2
    x1
    -0

    Add up the permission values for owner, group, and others respectively:

    NumberPermissionDescription
    7rwxRead + write + execute
    6rw-Read + write
    5r-xRead + execute
    4r--Read-only
    3-wxWrite + execute
    2-w-Write-only
    1--xExecute-only
    0---No permissions
    Set permissions to 755 (owner rwx, group r-x, others r-x)
    $ chmod 755 script.sh
    Set permissions to 644 (owner rw-, group r--, others r--)
    $ chmod 644 config.conf
    Set permissions to 700 (owner rwx, no permissions for others)
    $ chmod 700 private-dir/
    Recursively change permissions on a directory and its contents
    $ chmod -R 755 /var/www/html/
    Set directories to 755 and files to 644 (recommended approach)
    $ find /var/www/html/ -type d -exec chmod 755 {} +
    $ find /var/www/html/ -type f -exec chmod 644 {} +

    chown and chgrp: Changing Ownership and Group

    Section titled “chown and chgrp: Changing Ownership and Group”
    Change the owner of a file
    $ sudo chown webuser /var/www/html/index.html
    Change both owner and group simultaneously
    $ sudo chown webuser:webgroup /var/www/html/index.html
    Recursively change the owner and group of a directory
    $ sudo chown -R webuser:webgroup /var/www/html/
    Change the group of a file
    $ sudo chgrp developers project-file.txt
    Recursively change the group of a directory
    $ sudo chgrp -R developers /opt/project/

    In addition to the basic rwx permissions, Linux has three special permission bits.

    When an executable file has the SUID bit set, any user who runs the file will execute it as the file’s owner (rather than as themselves).

    A classic SUID example: the passwd command
    $ ls -l /usr/bin/passwd
    -rwsr-xr-x. 1 root root 32648 ... /usr/bin/passwd

    The s in the owner permission is the SUID flag. When a regular user runs passwd, the process runs as root, allowing it to modify /etc/shadow.

    Set SUID (octal prefix 4)
    $ sudo chmod u+s /path/to/program
    $ sudo chmod 4755 /path/to/program
    Find all files with SUID set on the system
    $ sudo find / -perm -4000 -type f 2>/dev/null

    For files: The process runs with the file’s group identity.

    For directories: New files and subdirectories created within the directory automatically inherit the directory’s group instead of the creator’s primary group. This is very useful for team collaboration directories.

    Set SGID (octal prefix 2)
    $ sudo chmod g+s /opt/shared-project/
    $ sudo chmod 2775 /opt/shared-project/
    Verify the SGID effect
    $ ls -ld /opt/shared-project/
    drwxrwsr-x. 2 root developers 4096 ... /opt/shared-project/

    The s in the group permission is the SGID flag.

    When the Sticky Bit is set on a directory, files within it can only be deleted by the file’s owner or root, even if other users have write permission on the directory. The most common example is /tmp.

    View the Sticky Bit on /tmp
    $ ls -ld /tmp
    drwxrwxrwt. 15 root root 4096 ... /tmp

    The t in the other users’ permission is the Sticky Bit flag.

    Set the Sticky Bit (octal prefix 1)
    $ sudo chmod +t /opt/shared-uploads/
    $ sudo chmod 1777 /opt/shared-uploads/
    PermissionOctalSymbolEffect on FilesEffect on Directories
    SUID4u+sExecute as the owner(No special effect)
    SGID2g+sExecute as the groupNew files inherit the directory’s group
    Sticky1+t(No special effect)Only the owner can delete files

    Practical Example: Creating a Team Shared Directory

    Section titled “Practical Example: Creating a Team Shared Directory”
    1. Create the shared directory

      Create the directory
      $ sudo mkdir /opt/team-share
    2. Set the owner and group

      Set ownership to the developers group
      $ sudo chown root:developers /opt/team-share
    3. Set permissions and SGID

      Set SGID to ensure new files inherit the group
      $ sudo chmod 2775 /opt/team-share
    4. Verify

      Confirm permissions are set correctly
      $ ls -ld /opt/team-share
      drwxrwsr-x. 2 root developers 4096 ... /opt/team-share

      Now any member of the developers group who creates files in this directory will have those files automatically belong to the developers group.

    5. Test

      Create a file as a developers group member
      $ touch /opt/team-share/test.txt
      $ ls -l /opt/team-share/test.txt
      -rw-rw-r--. 1 zhangsan developers 0 ... test.txt

    umask determines the default permissions for newly created files and directories. The permissions of a new file = base permissions - umask value.

    • Base permissions for files: 666 (no execute bit)
    • Base permissions for directories: 777
    View the current umask
    $ umask
    0022
    View in symbolic form
    $ umask -S
    u=rwx,g=rx,o=rx

    Effect of umask 0022:

    Base PermissionsumaskActual Permissions
    File666022644 (rw-r—r—)
    Directory777022755 (rwxr-xr-x)
    Temporarily change umask (current session only)
    $ umask 027

    Effect of umask 027:

    Base PermissionsumaskActual Permissions
    File666027640 (rw-r-----)
    Directory777027750 (rwxr-x---)
    Permanently change a user's umask
    $ echo "umask 027" >> ~/.bashrc

    When the basic owner/group/other permission model is insufficient, ACLs allow you to set independent permissions for specific users or groups.

    View a file's ACL
    $ getfacl /opt/team-share/config.txt

    Example output (no additional ACL):

    opt/team-share/config.txt
    # owner: zhangsan
    # group: developers
    user::rw-
    group::rw-
    other::r--
    Grant read-write permission to a specific user
    $ sudo setfacl -m u:lisi:rw /opt/team-share/config.txt
    Grant read-only permission to a specific group
    $ sudo setfacl -m g:qa:r /opt/team-share/config.txt
    View the ACL after changes
    $ getfacl /opt/team-share/config.txt

    Example output:

    opt/team-share/config.txt
    # owner: zhangsan
    # group: developers
    user::rw-
    user:lisi:rw-
    group::rw-
    group:qa:r--
    mask::rw-
    other::r--
    Set a user ACL
    $ sudo setfacl -m u:username:permissions filepath
    Set a group ACL
    $ sudo setfacl -m g:groupname:permissions filepath
    Remove a specific user's ACL
    $ sudo setfacl -x u:lisi /opt/team-share/config.txt
    Remove a specific group's ACL
    $ sudo setfacl -x g:qa /opt/team-share/config.txt
    Remove all ACLs from a file
    $ sudo setfacl -b /opt/team-share/config.txt
    Recursively set ACLs on a directory
    $ sudo setfacl -R -m u:lisi:rwx /opt/team-share/

    Default ACLs cause newly created files within a directory to automatically inherit ACL rules:

    Set default ACLs
    $ sudo setfacl -d -m u:lisi:rw /opt/team-share/
    $ sudo setfacl -d -m g:qa:r /opt/team-share/
    View default ACLs
    $ getfacl /opt/team-share/

    Example output:

    # file: opt/team-share/
    # owner: root
    # group: developers
    # flags: -s-
    user::rwx
    group::rwx
    other::r-x
    default:user::rwx
    default:user:lisi:rw-
    default:group::rwx
    default:group:qa:r--
    default:mask::rwx
    default:other::r-x

    Now new files created in this directory will automatically include ACL rules for lisi and the qa group.

    The mask defines the maximum permissions that users and groups can have in the ACL. Even if you set a user’s permissions to rwx, if the mask is r--, the user’s effective permissions will only be r--.

    Set the mask
    $ sudo setfacl -m m::rx /opt/team-share/config.txt

    Practical Example: Fine-Grained Project Permission Control

    Section titled “Practical Example: Fine-Grained Project Permission Control”

    Suppose you have the following requirements:

    • The project directory /opt/webapp belongs to the webdev group
    • Members of the webdev group have full read-write access
    • The qa group can only read, not modify
    • User deployer has full access for deployments
    • Newly created files automatically inherit these rules
    1. Create the directory and groups

      Create the directory and groups
      $ sudo mkdir -p /opt/webapp
      $ sudo groupadd webdev
      $ sudo groupadd qa
    2. Set basic permissions

      Set owner, group, and SGID
      $ sudo chown root:webdev /opt/webapp
      $ sudo chmod 2770 /opt/webapp
    3. Set ACLs

      Read-only permissions for the qa group
      $ sudo setfacl -m g:qa:rx /opt/webapp
      Full permissions for the deployer user
      $ sudo setfacl -m u:deployer:rwx /opt/webapp
    4. Set default ACLs (applied to newly created files)

      Set default ACLs
      $ sudo setfacl -d -m g:webdev:rwx /opt/webapp
      $ sudo setfacl -d -m g:qa:rx /opt/webapp
      $ sudo setfacl -d -m u:deployer:rwx /opt/webapp
    5. Verify

      View the complete ACL settings
      $ getfacl /opt/webapp

    ACLs are an extension of basic permissions. When both exist:

    • The file owner’s permissions are still controlled by user::
    • Other users’ permissions are jointly affected by ACL rules and the mask
    • chmod on group permissions modifies the mask value when ACLs are present

    The File Owner is root, but Regular Users Can Still Read It

    Section titled “The File Owner is root, but Regular Users Can Still Read It”

    Because the other (other users) permission allows reading. For example, permissions of 644 mean all users can read the file.

    How to Determine Why a User Cannot Access a File

    Section titled “How to Determine Why a User Cannot Access a File”
    Check file permissions and ACL
    $ ls -la /path/to/file
    $ getfacl /path/to/file
    Check permissions at every level of the directory path
    $ namei -l /path/to/file

    namei -l displays the permissions of each directory level in the path, helping you identify which level is blocking access.

    Back up ACLs to a file
    $ getfacl -R /opt/webapp > acl-backup.txt
    Restore ACLs from a backup
    $ sudo setfacl --restore=acl-backup.txt