Linux Permissions, umask, and grep
These practical notes cover real-world Linux security and file search techniques: numeric permissions such as 0755, special permission bits (SUID, SGID, and sticky bit), default umask calculations, and essential grep options.
1. Linux File Permissions
Linux permissions answer three fundamental questions for every filesystem operation:
- Who is accessing the file? (Owner, group, or others).
- What are they allowed to do? (Read, write, or execute).
- Where do the permissions apply? (To a regular file or a directory).
1.1 The Three Basic Permissions
Permissions behave differently on regular files versus directories:
| Permission | Number | On a regular file | On a directory |
|---|---|---|---|
Read (r) |
4 |
Read the file's contents | List names in the directory (e.g., with ls) |
Write (w) |
2 |
Modify the file's contents | Create, delete, or rename directory entries (subject to directory rules) |
Execute (x) |
1 |
Run the file as a program or script | Enter/traverse the directory (e.g., cd) and access items by name |
The three permission classes are:
u)
The individual user account that owns the file.
g)
Users who belong to the file's assigned group.
o)
Everyone else on the system with access.
1.2 Reading ls -l
Consider this standard long-format directory listing:
-rwxr-xr-- 1 alice devs 2048 Nov 3 10:00 deploy.shRead each field from left to right:
-: Regular file (dindicates a directory;lindicates a symbolic link).rwx: Owner (alice) can read, write, and execute.r-x: Group (devs) can read and execute.r--: Others can read only.alice: File owner user account.devs: Group assigned to the file.
1.3 How Numeric Permissions Work
Each permission has an assigned octal weight:
- Read =
4 - Write =
2 - Execute =
1
Add the numbers together to calculate the permission digit for each class:
| Number | Permission | Meaning |
|---|---|---|
0 | --- | No permissions |
1 | --x | Execute only |
2 | -w- | Write only |
3 | -wx | Write and execute (2 + 1) |
4 | r-- | Read only |
5 | r-x | Read and execute (4 + 1) |
6 | rw- | Read and write (4 + 2) |
7 | rwx | Read, write, and execute (4 + 2 + 1) |
A standard three-digit mode defines owner, group, and others in order. For example:
# Sets owner=rwx (7), group=r-x (5), others=r-x (5)
$ chmod 755 deploy.shThe leading zero in 0755 is optional in standard chmod usage; it explicitly denotes that no special permission bits (SUID, SGID, or sticky) are set.
Common modes in production environments:
| Mode | Symbolic form | Typical use |
|---|---|---|
755 |
rwxr-xr-x |
Executable scripts, system binaries, public directories |
644 |
rw-r--r-- |
Regular text files, source code, web pages, configs |
600 |
rw------- |
Confidential files, SSH private keys (~/.ssh/id_rsa) |
700 |
rwx------ |
Private user directories such as ~/.ssh |
750 |
rwxr-x--- |
Directories accessible only to owner and group members |
664 |
rw-rw-r-- |
Group-writable collaborative files |
775 |
rwxrwxr-x |
Group-writable shared directories |
1.4 Useful Permission Commands
# Show file permissions, owner, and group
$ ls -l file
# Show directory permissions itself (not its contents)
$ ls -ld directory
# Detailed file metadata and numeric octal mode
$ stat file
# Set numeric permissions
$ chmod 755 file
# Add execute permission for owner only
$ chmod u+x file
# Remove group write and strip all access for others
$ chmod g-w,o-rwx file
# Add read permission for all classes (user, group, others)
$ chmod a+r file
# Apply permissions recursively through directories
$ chmod -R 750 directory
# Change file owner (requires root or sudo)
$ sudo chown bob file
# Change owner and group simultaneously
$ sudo chown bob:devs file
# Change group ownership only
$ chgrp devs file
# Show current user's UID, GID, and supplementary groups
$ id
# Trace permissions on each path component to diagnose permission issues
$ namei -l /path/to/file2. Special Permission Bits: SUID, SGID and Sticky Bit
A four-digit octal permission string specifies a special-permission digit followed by the traditional owner, group, and others digits:
4 7 5 5
| | | |
| | | +-- Others
| | +------ Group
| +---------- Owner
+-------------- Special bitsThe special digit is formed by summing these values:
| Value | Special bit | Main idea |
|---|---|---|
4 |
SUID (Set User ID) | Executable runs with the file owner's effective user ID rather than the caller's ID. |
2 |
SGID (Set Group ID) | Executable runs with the file group's effective GID; on directories, newly created items inherit the directory's group. |
1 |
Sticky bit | On shared directories, prevents users from deleting or renaming files they do not own. |
2.1 SUID — Value 4
SUID means Set User ID. When SUID is enabled on an executable binary, the operating system launches the process with the file owner's effective user ID rather than the user ID of whoever ran the command.
Real-World Example: passwd
The passwd binary is owned by root and has SUID enabled. When an unprivileged user executes passwd to change their password, the program executes with root privileges to update protected shadow files (such as /etc/shadow), while enforcing its own strict internal validation.
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Nov 3 10:00 /usr/bin/passwdNotice the s in the owner's execute position. You can set SUID numerically or symbolically:
# Numerically: 4 denotes SUID, 755 denotes standard permissions
$ chmod 4755 program
# Symbolically:
$ chmod u+s programJohn and AK Example
Suppose AK owns a SUID executable and John executes it. While that process runs, its effective user ID is AK's user ID. If the binary opens a file that AK has permission to read, the kernel allows access based on the process's effective credentials.
John does not permanently become AK and does not inherit general access to AK's private account. The binary must explicitly perform the operation, and its internal programming and system security controls determine what John can do.
2.2 SGID — Value 2
SGID means Set Group ID. Its behavior depends on whether it is placed on an executable file or a directory:
On an Executable File
The binary executes with the file's effective group ID. The s appears in the group execute position:
# Set SGID on binary
$ chmod 2755 program
# or symbolically:
$ chmod g+s program
$ ls -l program
-rwxr-sr-x 1 root devs 14820 Nov 3 10:00 programOn a Directory: Shared Team Folder
Normally, when a user creates a new file, the file's group is set to the user's primary group. When SGID is set on a shared directory (e.g., /srv/project), any newly created file or subdirectory automatically inherits the group of the parent directory.
# 1. Assign ownership to root and devs group
$ sudo chown root:devs /srv/project
# 2. Add SGID (2) + read/write/execute for owner and group (775)
$ sudo chmod 2775 /srv/project
# 3. Verify directory permissions
$ ls -ld /srv/project
drwxrwsr-x 2 root devs 4096 Nov 3 10:00 /srv/projectThis allows team members belonging to devs to collaborate smoothly without manually running chgrp on every new file.
2.3 Sticky Bit — Value 1
The sticky bit is used on shared directories where multiple users have write access. It restricts file deletion and renaming: only the file's owner, the directory's owner, or root can delete or rename the file.
Real-World Example: /tmp
All users need to write temporary files to /tmp. Without the sticky bit, any user could delete another user's critical temporary files because they have write permissions on the directory. The sticky bit solves this problem.
$ ls -ld /tmp
drwxrwxrwt 18 root root 4096 Nov 3 10:00 /tmpNotice the t in the others execute position. You can set the sticky bit numerically or symbolically:
# Numerically (1 denotes sticky bit, 777 denotes read/write/execute for all)
$ chmod 1777 shared-directory
# Symbolically
$ chmod +t shared-directory2.4 What Do s, S, t, and T Mean?
When you inspect permissions with ls -l, letters indicate whether underlying execute permissions are present alongside special bits:
| Symbol | Location in ls -l |
Meaning |
|---|---|---|
s (lowercase) |
Owner execute position | SUID is set and owner execute (x) is set |
S (uppercase) |
Owner execute position | SUID is set, but owner execute (x) is not set |
s (lowercase) |
Group execute position | SGID is set and group execute (x) is set |
S (uppercase) |
Group execute position | SGID is set, but group execute (x) is not set |
t (lowercase) |
Others execute position | Sticky bit is set and others execute (x) is set |
T (uppercase) |
Others execute position | Sticky bit is set, but others execute (x) is not set |
2.5 All Combinations of the Special Digit
The first digit of a 4-digit octal permission string represents the special bit sum:
| First digit | Special bits enabled |
|---|---|
0 | None (standard permissions) |
1 | Sticky bit |
2 | SGID |
3 | SGID + Sticky bit (2 + 1) |
4 | SUID |
5 | SUID + Sticky bit (4 + 1) |
6 | SUID + SGID (4 + 2) |
7 | SUID + SGID + Sticky bit (4 + 2 + 1) |
Common modes combining special and normal permissions:
| Mode | Meaning |
|---|---|
0755 | No special bits; standard 755 (rwxr-xr-x) |
1755 | Sticky bit + normal 755 permissions |
2755 | SGID + normal 755 permissions |
3755 | SGID + Sticky bit + normal 755 permissions |
4755 | SUID + normal 755 permissions |
5755 | SUID + Sticky bit + normal 755 permissions |
6755 | SUID + SGID + normal 755 permissions |
7755 | SUID + SGID + Sticky bit + normal 755 permissions |
Auditing SUID and SGID Files on a Server
# Find all SUID executables across the root filesystem
$ sudo find / -xdev -type f -perm -4000 2>/dev/null
# Find all SGID executables across the root filesystem
$ sudo find / -xdev -type f -perm -2000 2>/dev/nullThe -xdev flag ensures the search stays on the local root filesystem, preventing unnecessary scanning of virtual or network mounts (such as /proc, /sys, or NFS).
3. Default Permissions with umask
umask is the user file-creation mask. It specifies which permission bits are filtered out (masked) when a program or user creates a new file or directory.
umask only affects newly created files and directories; it does not change permissions on items that already exist.
3.1 How umask Works
When an application creates an item, it specifies base permissions:
- Regular files base mode:
666(rw-rw-rw-— no execute by default for safety). - Directories base mode:
777(rwxrwxrwx— execute is needed to enter directories).
The umask clears selected bits from that base mode using bitwise subtraction (Base AND (NOT Mask)).
For example, with a mask of 027:
| Digit | Applies to | Bits removed |
|---|---|---|
0 | Owner (u) | None (owner keeps full requested rights) |
2 | Group (g) | Write (w) removed |
7 | Others (o) | Read, write, and execute (rwx) removed |
3.2 Real Example: Creating a File
$ umask 027
$ touch shan.txt
$ ls -l shan.txt
-rw-r----- 1 ak ak 0 Nov 3 10:00 shan.txtCalculation: Base 666 minus mask 027 results in 640:
- Owner:
6=rw-(Read and write) - Group:
4=r--(Read only) - Others:
0=---(No access at all)
3.3 Real Example: Creating a Directory
$ umask 027
$ mkdir myfolder
$ ls -ld myfolder
drwxr-x--- 2 ak ak 4096 Nov 3 10:00 myfolderCalculation: Base 777 minus mask 027 results in 750:
- Owner:
7=rwx(Full access) - Group:
5=r-x(Can enter and list files, but cannot create or delete items) - Others:
0=---(No access at all)
3.4 Common umask Values
| Umask | New regular file (usual) | New directory (usual) | General security effect |
|---|---|---|---|
022 |
644 (rw-r--r--) |
755 (rwxr-xr-x) |
Standard default on many distributions. Group and others can read/enter, but cannot modify. |
027 |
640 (rw-r-----) |
750 (rwxr-x---) |
Hardened server environment. Others get zero access; group cannot write. |
077 |
600 (rw-------) |
700 (rwx------) |
Strict privacy mode. Only the file owner has access. |
002 |
664 (rw-rw-r--) |
775 (rwxrwxr-x) |
Team collaboration mode. Group members can write; others can read only. |
3.5 Useful umask Commands
# Show current mask in octal format
$ umask
0022
# Show mask symbolically
$ umask -S
u=rwx,g=rx,o=rx
# Set mask for the active shell and child processes
$ umask 0274. Searching Text Inside Files with grep
grep (Global Regular Expression Print) searches text input or files for lines that match a specified pattern and prints the matching lines to standard output.
Suppose we have a sample log file named log.txt:
server started
connection error
login successful
database ERROR
payment failed
system running4.1 Basic Search
$ grep "error" log.txt
connection errorBy default, grep is case-sensitive, so it matches lowercase error, but ignores uppercase ERROR.
4.2 Common grep Options
| Option | Meaning | Example |
|---|---|---|
-i |
Ignore case distinctions | grep -i "error" log.txt |
-v |
Invert match: print non-matching lines | grep -v "error" log.txt |
-n |
Prefix each match with its line number | grep -n "error" log.txt |
-c |
Print count of matching lines | grep -c "error" log.txt |
-r |
Search directories recursively | grep -r "error" logs/ |
-E |
Use Extended Regular Expressions (ERE) | grep -E "error|fail" log.txt |
-w |
Match whole words only | grep -w "error" log.txt |
-l |
Print only names of files with matching lines | grep -rl "error" logs/ |
-A 3 |
Show 3 lines of context after match | grep -A 3 "error" log.txt |
-B 2 |
Show 2 lines of context before match | grep -B 2 "error" log.txt |
-i: Ignore Case
$ grep -i "error" log.txt
connection error
database ERRORMatches error, ERROR, Error, and mixed casing.
-v: Invert Match (Filter Out Noise)
$ grep -v "error" log.txt
server started
login successful
database ERROR
payment failed
system runningUseful for stripping known healthy heartbeat entries or commented lines (e.g., grep -v '^#' config.conf).
-n: Line Numbers
$ grep -n "error" log.txt
2:connection errorPrints the exact line number where each match was found in the source file.
-c: Count Matching Lines
$ grep -c "error" log.txt
1
$ grep -ic "error" log.txt
2Counts matching lines (not the total number of words if a word appears multiple times on one line).
-r: Recursive Search
Suppose you have a directory tree of log files:
logs/
app.log
error.log
archive/
old.logSearch every file in logs/ and its subdirectories:
$ grep -r "error" logs/
logs/app.log:connection error
logs/archive/old.log:fatal disk error-E: Extended Regular Expressions & OR Alternation
$ grep -E "err|fail" log.txt
connection error
payment failedThe pipe character | functions as a logical OR operator. In basic grep, | is treated literally unless escaped with backslashes. -E enables clean, readable modern regex patterns.
More regex examples:
# Contains error OR warning
$ grep -E "error|warning" log.txt
# Either pattern, ignoring case
$ grep -Ei "error|fail" log.txt
# Line starts with ERROR or starts with FATAL
$ grep -E "^ERROR|^FATAL" log.txt
# Contains error OR ends with fail
$ grep -E "error|fail$" log.txt4.3 Difference Between -i, -r, and -E
Each flag addresses an entirely distinct dimension of the search:
-i: Case Sensitivity
Modifies pattern matching logic to be case-insensitive.
-r: Search Scope
Traverses directories recursively instead of inspecting a single file.
-E: Syntax Engine
Enables Extended Regular Expressions (alternation, groupings, quantifiers).
Flags can be combined into compact expressions:
# Search recursively (-r), ignore case (-i), show line numbers (-n), with regex alternation (-E)
$ grep -rinE "error|fail" /var/log/4.4 Practical Server-Log Examples
# Find errors in system log without worrying about case
$ grep -i "error" /var/log/syslog
# Find errors and failures with line numbers
$ grep -inE "error|fail" /var/log/syslog
# Search all log files under /var/log recursively
$ grep -ri "error" /var/log/
# Count total error lines ignoring case
$ grep -ic "error" /var/log/syslog
# Show context around errors (2 lines before, 3 lines after)
$ grep -B 2 -A 3 -i "error" /var/log/syslog
# List only file paths containing matches (handy for scripting)
$ grep -rl "error" /var/log/5. Quick Comparison: Commands Cheatsheet
| Topic | Command | What it does |
|---|---|---|
| Normal permissions | chmod 755 file |
Sets Owner rwx, Group and Others r-x |
| SUID | chmod 4755 program |
Sets SUID on executable binary (runs with owner credentials) |
| SGID | chmod 2755 program |
Sets SGID on binary; on directories use chmod 2775 dir for group inheritance |
| Sticky bit | chmod 1777 directory |
Restricts deletion or renaming of entries in shared directories |
| Check umask | umask |
Displays current creation mask in octal format |
| Set umask | umask 027 |
Sets default file-creation mask for current shell |
| Basic grep | grep "error" file |
Prints lines containing pattern error |
| Ignore case | grep -i "error" file |
Matches pattern regardless of case (Error, ERROR) |
| Invert match | grep -v "error" file |
Prints only lines that do not contain the pattern |
| Line numbers | grep -n "error" file |
Prints matching line numbers alongside matching lines |
| Count lines | grep -c "error" file |
Prints total count of matching lines |
| Recursive search | grep -r "error" dir/ |
Searches all files inside a directory and its subdirectories |
| Extended patterns | grep -E "err|fail" file |
Matches either err OR fail using regex alternation |
6. Practice Exercises
Exercise A: Permissions
$ mkdir linux-lab && cd linux-lab
$ touch notes.txt
$ chmod 640 notes.txt
$ ls -l notes.txtReview Questions:
- Can the file owner read and modify the file? (Yes,
6=rw-) - Can users in the file's group write to it? (No,
4=r--, read-only) - Can others on the system read it? (No,
0=---, access denied)
Expected mode output: -rw-r-----.
Exercise B: Default umask
$ umask 027
$ touch private-report.txt
$ mkdir team-folder
$ ls -l private-report.txt
$ ls -ld team-folderExpected Modes:
- Regular file (Base
666-027):640(-rw-r-----) - Directory (Base
777-027):750(drwxr-x---)
Exercise C: Text Search with grep
Create a sample test log:
$ cat > app.log <<'EOF'
server started
connection error
login successful
database ERROR
payment failed
system running
EOFTest each variation and observe how the output changes:
# 1. Matches only lowercase 'error'
$ grep "error" app.log
# 2. Matches both 'error' and 'ERROR'
$ grep -i "error" app.log
# 3. Prints lines that do not have 'error'
$ grep -v "error" app.log
# 4. Shows line number: 2:connection error
$ grep -n "error" app.log
# 5. Counts matching lines
$ grep -c "error" app.log
# 6. Matches error OR failed
$ grep -E "error|failed" app.log
# 7. Matches error OR failed (case-insensitive)
$ grep -Ei "error|failed" app.log7. Key Points to Remember
- Octal values:
r = 4,w = 2,x = 1. Sum them to compute each permission digit for user, group, and others. - Mode prefixes:
0755sets no special bits;4755enables SUID,2755enables SGID, and1755enables the sticky bit. - SUID execution: Grants a process the file owner's effective user identity during execution; it does not permanently elevate the user's account.
- SGID on directories: Causes newly created files and subdirectories to automatically inherit the parent directory's group.
- Sticky bit protection: Prevents users in shared directories (like
/tmp) from removing or renaming files belonging to other users. - umask role: Influences the default initial permissions of newly created files and directories; it has no effect on pre-existing files.
- Essential grep flags:
-iignores case,-vinverts matches,-nnumbers lines,-ccounts lines,-rsearches directories recursively, and-Eenables extended regex alternation. - Verification habits: Always confirm permission and file changes using
ls -l,ls -ld, orstat.