A catalog service starts successfully in a developer's shell but fails in production:
The file exists. Its contents are valid. The failure occurs because the production process carries different user and group credentials, and the file-system permission check does not authorize that process to read the file.
Unix file permissions connect two pieces of state:
Process credentials combined with the file's ownership and mode decide whether an operation is allowed or denied.
Permissions do not belong to a pathname or program name. They are inode metadata evaluated against the credentials of the process performing an operation.
The basic model uses an owning user, an owning group, and read, write, and execute bits for three permission classes. The bit meanings change in important ways for directories.
ls -l displays a file's type, permissions, ownership, and other metadata:
Focus first on:
| Field | Value | Meaning |
|---|---|---|
-rw-r----- | Type and mode bits | A regular file, with the permissions below |
root | Owning user | |
catalog | Owning group |
The first character describes the file-system object type:
The next nine characters form three groups:
| Class | Bits |
|---|---|
| Owner | rw- |
| Group | r-- |
| Other | --- |
Each group has positions for:
For database.conf:
The characters describe mode bits. They do not say which user is currently running a command, and they are not by themselves a complete record of every possible security policy.
Loading simulation...
The kernel does not combine all three permission triplets and choose whichever is most generous. It selects the class that applies to the calling process.
For the basic mode-bit decision:
Suppose a file has:
Its symbolic mode is:
The owner class has read permission, the group class has none, and other has read permission.
If Alice accesses the file, the kernel selects the owner class. It does not fall through to the more permissive other class. If a member of backend who is not Alice accesses it, the kernel selects the group class and denies the read. A process matching neither uses other and can read.
This “select one class” rule prevents permission reasoning from becoming an accidental union of unrelated bits.
Privileged processes and additional access-control mechanisms can alter the final authorization result. The diagram describes the ordinary owner/group/other mode-bit check.
Permission modes are commonly written in octal because each three-bit group maps cleanly to one digit.
Add the values within each class:
Mode 0640 means:
Mode 0755 means:
The leading zero in C source marks an octal integer literal:
Shell tools such as chmod conventionally interpret a three- or four-digit permission operand as octal:
Do not read 0750 as decimal seven hundred and fifty. It is a compact representation of permission bits.
chmod also accepts symbolic expressions:
Operators add, remove, or assign permissions:
Examples:
Symbolic modes are often clearer in scripts that intend to make one narrow change. Numeric modes are convenient when the complete desired state is known.
Inspect both forms with GNU stat:
A result might be:
For a regular file, the basic bits mean:
Read permission allows opening the file for reading and obtaining its application bytes.
It does not require execute permission. A process can read a source file or image without being allowed to execute it.
Write permission allows modifying file contents, including overwriting bytes or truncating the file when the operation and surrounding path permit it.
Write permission on the file does not by itself control whether its pathname can be removed. Removal changes a directory entry, so the parent directory's permissions are central.
Execute permission allows the file to be considered for program execution.
The bit alone does not make arbitrary bytes into a runnable program. The file must also have a format the operating system can load or an interpreter declaration the system can process. Mount options and broader security rules can still prohibit execution.
A script can therefore be readable but not directly executable:
It can be supplied as input to an interpreter the process is allowed to run:
but direct execution:
requires suitable execute permission in addition to valid script structure.
The same letters have namespace-oriented meanings on a directory.
Read permission allows enumerating directory entries:
Without search permission, the process may see names but be unable to obtain useful metadata or open the named objects.
Write permission participates in creating, removing, and renaming names inside the directory.
Useful namespace modification normally also requires search permission. Write without search is rarely sufficient for ordinary work.
Execute permission on a directory means search permission. It lets path resolution use known component names and pass through the directory.
For:
the process needs search permission on /, /srv, /srv/catalog, and /srv/catalog/config. The final regular file's mode is checked for the requested read or write.
This explains why a readable file can still produce EACCES: an earlier directory can block the path walk.
Loading simulation...
Consider:
The file itself has no write bit. A process allowed to modify entries in reports/ may nevertheless be able to unlink final.csv.
Unlinking removes the name from the directory. It does not edit bytes through the regular file's write interface.
The reverse can also occur. A process may be able to modify a file's contents but lack permission to remove its name because the parent directory is not writable:
A catalog group process can modify runtime.conf but cannot add, remove, or rename entries in config/.
Renaming generally requires appropriate write and search access in the involved source and destination directories. File ownership alone does not grant authority to restructure the containing namespace.
Additional rules such as the sticky bit can further restrict deletion and rename.
A world-writable directory lets many users create entries. Without an additional restriction, its write permission could also let one user remove another user's names.
The sticky bit limits removal and rename inside such a directory. In the common Linux case, an entry can be removed or renamed by:
/tmp is the familiar example:
A common result is:
Its numeric mode is commonly:
The leading 1 represents the sticky bit. The remaining 777 grants read, write, and search to all three ordinary classes.
Sticky does not make file contents private. A file created with world-readable mode inside /tmp can still be read by others. It narrows who can remove or rename the directory entry.
The set-group-ID, or setgid, bit has a practical directory meaning. New objects created inside a setgid directory normally inherit the directory's owning group rather than taking only the creator's default group.
Create a collaborative directory:
The leading 2 sets the setgid bit:
Files created by different members can now consistently belong to group backend, assuming the rest of the ownership and access policy permits creation. New subdirectories commonly inherit setgid as well.
Setgid does not automatically grant group write permission to every new file. The creating program's requested mode, the process's creation mask, and any default ACL still determine the new permission bits.
On an executable regular file, setgid has a different meaning: execution can establish an effective group identity from the file's owning group. That is a privilege boundary and should be used only for carefully designed programs.
The set-user-ID, or setuid, bit on an executable can cause a newly executed process to receive an effective user identity based on the executable's owner.
Its numeric value is the leading 4:
In ls -l, a setuid executable with owner execute permission shows:
Setuid programs let an ordinary user perform a narrowly implemented operation with another identity's authority. They are security-sensitive because every input, environment assumption, file operation, and error path reachable with that authority becomes part of the trust boundary.
Systems commonly ignore or restrict setuid behavior on scripts, on mounts configured with nosuid, or under other security policies. The bit is metadata requesting special execution behavior, not a universal guarantee that privilege will change.
For ordinary service data, setgid directories and well-chosen ownership are far more common than setuid files.
S and T: Missing Execute PermissionSpecial bits occupy positions normally used to display execute bits.
For example:
has setuid metadata but no owner execute bit. It will not gain normal setuid execution behavior because it is not executable by that class.
Similarly:
has the sticky bit but lacks other search permission, so the visible T warns that the paired execute/search bit is absent.
umaskWhen a program creates a file or directory, it requests an initial mode. The process's file mode creation mask, or umask, removes selected bits:
Regular-file creation commonly requests 0666:
Execute bits are absent because creating data should not make it executable by default.
Directory creation commonly requests 0777 because directories need search bits to be usable.
With umask 0027:
Inspect or set a shell's mask:
The mask can only remove bits the application requested. A umask of 0000 does not add execute permission to a file created with requested mode 0666.
Changing the umask does not modify existing files. It affects later creations by the process and is inherited by child processes.
Threads in one process share the creation mask. Temporarily changing it around one creation can race with other threads creating files. Multithreaded services should normally establish the intended umask during startup or request restrictive modes directly.
A default directory ACL can participate in creation using richer inheritance rules, so the simple bit formula is the ordinary mode-only model.
chmod, fchmod, chown, and chgrpchmod() changes mode bits through a pathname:
fchmod() changes the object reached through an already open descriptor:
Descriptor-based modification avoids repeating a pathname lookup that could now reach a different object.
The shell provides:
Only an authorized process can change an object's mode. The owner can normally change its permission bits, while changing ownership is more restricted because arbitrary ownership transfer would undermine accounting and access boundaries.
chown changes the owning user, and chgrp changes the owning group:
The kernel limits which ownership changes an unprivileged process may perform. Ownership changes can also clear setuid or setgid bits to avoid accidentally preserving privilege metadata after control of a file changes.
When a process opens a regular file, the kernel checks the requested access against the resolved object and process credentials. If allowed, the resulting open file description records an access mode such as read-only or write-only.
Changing the inode's permissions later does not normally revoke an already granted descriptor:
The existing descriptor is a capability-like reference to the already opened object. Unix mode changes are not a general mechanism for recalling access already handed out.
This matters during incident response and secret rotation. Removing read permission can prevent new opens, but a process that already holds the file open may retain access until it closes the descriptor or exits.
The descriptor's own access mode still applies. Duplicating a read-only descriptor does not turn it into a writable descriptor, even if the inode's mode later allows writing.
access() for Pre-Open Authorizationaccess(path, mode) asks whether a pathname would pass an access check under specific credential rules. It is tempting to write:
Another process can replace a path component between the check and the open. The two calls may operate on different objects.
The safer pattern is:
Attempt the actual open. If it succeeds, use that descriptor, and if it fails, handle errno.
An application should not duplicate the kernel's permission decision and then assume the later operation must succeed. The requested operation is the authoritative check.
access() also has credential semantics designed partly for setuid-style programs, so it is not a universal “can this process open the file?” predicate.
Hard links refer to one inode. All hard-link names therefore expose the same owner, group, and mode:
Running chmod through either name changes the shared inode and is visible through both.
A symbolic link has its own inode, but ordinary access through the link follows the target and checks the target object plus the directories traversed. On Linux, the familiar lrwxrwxrwx shown for a symlink is not a promise of target access.
Opening current/config.json still requires search access through the resolved directories and suitable access to config.json.
Removing the symlink is controlled primarily by the containing directory, not by the target file's mode.
Owner, group, and other bits are the foundation, but a real system can apply additional rules.
A POSIX access-control list can grant permissions to specifically named users or groups. ls -l commonly shows a trailing + when extended ACL information is present:
Inspect such rules with:
A read-only mount can reject writes even when the inode has a write bit. File-system flags can restrict modification. Mandatory security policies can add checks beyond the file owner’s discretionary mode. Privileged processes can bypass some ordinary checks while still being constrained by other layers.
Consequently:
chmod 777changes one layer of policy; it is neither a complete diagnostic method nor a complete authorization guarantee.
When a mode appears sufficient but an operation fails, inspect the whole path, process credentials, ACLs, mount state, and active security policy before broadening permissions.
Consider a service running as user catalog and group catalog. A log collector belongs to group catalog-logs.
The configuration contains credentials that only the service should read:
The executable should be writable only by its deployment owner but executable by the service:
The log directory can use a shared group and setgid:
New logs requested as 0666 under umask 0027 become 0640:
This layout expresses the intended responsibilities:
Giving every object mode 0777 would erase these boundaries and still would not solve failures caused by a read-only mount or additional security policy.
Create a temporary workspace:
Inspect the initial mode:
Set an explicit restrictive mode:
The result is:
Use a symbolic change:
The mode becomes:
The example adds execute only to the owner, removes group write if present, and removes all other permissions.
Observe umask behavior in a subshell so the parent shell's mask is unchanged:
Typical output is:
The shell requested ordinary file and directory modes; umask removed group write and all other permissions.
Inspect a shared sticky directory:
Many Linux systems report:
The exact ownership and policies can vary, but the final t exposes the sticky bit.
The following program uses lstat() and formats the traditional type and mode bits. It demonstrates how tools derive strings such as -rwsr-x--- from st_mode.
Compile and run:
The program reports the final symbolic-link object itself because it uses lstat(). It formats only traditional type and mode bits; it does not display ACLs or decide whether the current process will pass every possible access-control layer.
Unix inode metadata records an owning user, owning group, and read, write, and execute bits for owner, group, and other. The kernel selects one applicable class from the process's credentials and checks whether that class contains the required bits.
For regular files, the bits govern reading contents, modifying contents, and execution. For directories, they govern listing names, modifying entries, and searching or traversing the namespace. Deletion and rename are primarily controlled through parent-directory permissions.
Octal modes encode r=4, w=2, and x=1. chmod changes existing modes, while umask removes requested bits during creation. Setgid directories support shared group ownership, sticky directories restrict removal in shared writable locations, and setuid or setgid executables can change execution authority.
Permission changes do not normally revoke already open descriptors. Mode bits are also only one authorization layer; ACLs, mount state, file-system flags, privilege, and broader security policy can affect the final result.
The central mental model is:
Select the applicable permission class, interpret its bits according to the object type, and remember that every traversed directory participates in the decision.
5 quizzes