Home › Linux · Lesson 3

Linux Permissions, umask, and grep

Lesson 3 of 3 · 15 min · Intermediate

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:

Owner (u) The individual user account that owns the file.
Group (g) Users who belong to the file's assigned group.
Others (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.sh

Read each field from left to right:

  • -: Regular file (d indicates a directory; l indicates 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--xExecute only
2-w-Write only
3-wxWrite and execute (2 + 1)
4r--Read only
5r-xRead and execute (4 + 1)
6rw-Read and write (4 + 2)
7rwxRead, 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.sh

The 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/file

2. 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 bits

The 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/passwd

Notice 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 program

John 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 program

On 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/project

This 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 /tmp

Notice 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-directory

2.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
0None (standard permissions)
1Sticky bit
2SGID
3SGID + Sticky bit (2 + 1)
4SUID
5SUID + Sticky bit (4 + 1)
6SUID + SGID (4 + 2)
7SUID + SGID + Sticky bit (4 + 2 + 1)

Common modes combining special and normal permissions:

Mode Meaning
0755No special bits; standard 755 (rwxr-xr-x)
1755Sticky bit + normal 755 permissions
2755SGID + normal 755 permissions
3755SGID + Sticky bit + normal 755 permissions
4755SUID + normal 755 permissions
5755SUID + Sticky bit + normal 755 permissions
6755SUID + SGID + normal 755 permissions
7755SUID + 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/null

The -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
0Owner (u)None (owner keeps full requested rights)
2Group (g)Write (w) removed
7Others (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.txt

Calculation: 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 myfolder

Calculation: 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 027

4. 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 running

4.1 Basic Search

$ grep "error" log.txt
connection error

By 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 ERROR

Matches 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 running

Useful 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 error

Prints 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
2

Counts 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.log

Search 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 failed

The 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.txt

4.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.txt

Review Questions:

  1. Can the file owner read and modify the file? (Yes, 6 = rw-)
  2. Can users in the file's group write to it? (No, 4 = r--, read-only)
  3. 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-folder

Expected 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
EOF

Test 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.log

7. Key Points to Remember

  1. Octal values: r = 4, w = 2, x = 1. Sum them to compute each permission digit for user, group, and others.
  2. Mode prefixes: 0755 sets no special bits; 4755 enables SUID, 2755 enables SGID, and 1755 enables the sticky bit.
  3. SUID execution: Grants a process the file owner's effective user identity during execution; it does not permanently elevate the user's account.
  4. SGID on directories: Causes newly created files and subdirectories to automatically inherit the parent directory's group.
  5. Sticky bit protection: Prevents users in shared directories (like /tmp) from removing or renaming files belonging to other users.
  6. umask role: Influences the default initial permissions of newly created files and directories; it has no effect on pre-existing files.
  7. Essential grep flags: -i ignores case, -v inverts matches, -n numbers lines, -c counts lines, -r searches directories recursively, and -E enables extended regex alternation.
  8. Verification habits: Always confirm permission and file changes using ls -l, ls -ld, or stat.

8. Frequently Asked Questions (FAQ)