Module 1 · Unit 2 · Lesson 4 of 5
Permissions and Access Control
The concrete rules that determine who can read, write, and execute every file on the system — and how to inspect them, modify them, and apply them safely.
01 Introduction
Every file on a Linux system carries a small piece of information that determines who can do what to it. This is the permission mode — a compact encoding of nine permissions that together answer three questions for every file: can the file's owner read it, write it, execute it? Can members of the file's group do so? Can everyone else?
The model is simple enough to fit on one line of
ls -l output, yet it governs an enormous range of
behaviour. Whether a server can bind to a privileged port,
whether a user can modify a configuration file, whether a
malicious script can overwrite a system binary, whether a
container can access a mounted volume — every one of these
decisions is ultimately a permission check.
This lesson covers the permission model in detail: the three permission types, the three categories of user, the numeric and symbolic notations, the tools for inspecting and modifying permissions, the umask mechanism, the special permission bits (setuid, setgid, sticky), and the practical discipline of least privilege that ties them together. It builds directly on the user and group model from Lesson 2.3.
02 Learning objectives
By the end of this lesson you will be able to
- Interpret permissions.
- Modify permissions.
- Explain ownership.
- Analyse security implications.
- Apply least privilege.
This lesson contributes to U2.4 and to course learning outcomes CLO6 and CLO7.
03 Required reading
-
Stevens & Rago — Advanced Programming
in the UNIX Environment, 3rd ed., Sections 4.4–4.7
(file access permissions, ownership, access testing). The
classical presentation of the model, including the
access()function and the semantics the kernel applies. -
Linux man pages:
man 1 chmod,man 1 chown,man 1 umask,man 2 chmod,man 7 acl,man 1 getfacl,man 1 setfacl. The definitive reference for permission syntax and behaviour. - Nemeth, E., Snyder, G., Whaley, B., & Mackin, D. — UNIX and Linux System Administration Handbook, 5th ed., Chapter 8 (access control). Practical treatment of permissions, ACLs, and the special bits.
Reading strategy
Read Stevens & Rago Sections 4.4–4.7 first for the model,
then consult the man pages for the specific commands. The
chmod man page in particular is worth reading
carefully — it documents both the numeric and symbolic
notations and the special permission bits, with more precision
than most tutorials.
04 Core content
4.1 The three permissions
For every file and directory, the system tracks three permissions:
- Read (r)
-
For a file: the contents may be read. Any
program that opens the file for reading will succeed. For
example,
cat file.txtworks.
For a directory: the list of names may be read. You can see which files are in the directory, though you may not be able to access them individually. This is whatlsdoes. - Write (w)
-
For a file: the contents may be modified.
Whether the file's length changes or not, writing to any
part of it requires write permission.
For a directory: entries may be created, renamed, or deleted within the directory. Note that changing a file's contents requires write permission on the file itself, not on its directory; changing the file's name or existence requires write permission on the directory. - Execute (x)
-
For a file: the file may be run as a
program. This applies to binaries and scripts. A file without
execute permission cannot be run directly (though it can be
passed to an interpreter, e.g.,
bash script.sh).
For a directory: the directory may be traversed — that is, it may be used as a component in a path. Without execute permission on a directory, you cannot access files inside it even if you know their names, because the kernel cannot resolve the path.
Directory permissions are not intuitive
The r/w/x meanings on directories are different from their meanings on files, and the difference trips up many users. The most common surprises: (1) a directory with read but not execute permission lets you list the names in it but not access the files; (2) a directory with execute but not read permission lets you access files whose names you already know, but not discover new names; (3) deleting a file requires write permission on the directory, not on the file.
4.2 The three categories of user
The permissions are tracked separately for three categories of principal:
- User (u)
- The file's owner — the UID recorded in the file's inode. This is usually the user who created the file, but ownership can be transferred (with appropriate privileges).
- Group (g)
- Members of the file's group — the GID recorded in the file's inode. A user is in the group if the file's GID matches their primary GID or any of their supplementary GIDs.
- Others (o)
- Everyone else — any user who is neither the owner nor a member of the file's group. Sometimes called "world".
Three permissions times three categories gives
nine permission bits, which is why the mode
fits so neatly in the output of ls -l.
4.3 Reading permissions with ls -l
The ls -l command prints a long-format listing that
begins with the file's mode. For example:
$ ls -l notes.txt
-rw-r--r-- 1 alice developers 4096 Oct 15 11:00 notes.txt
Breaking the first field -rw-r--r-- apart:
-
First character: file type.
-regular file,ddirectory,lsymlink,ccharacter device,bblock device,pFIFO (named pipe),ssocket. -
Characters 2–4: owner permissions.
rw-means the owner (alice) can read and write but not execute. -
Characters 5–7: group permissions.
r--means members of the group (developers) can read but not write or execute. -
Characters 8–10: others permissions.
r--means everyone else can read but not write or execute.
4.4 Numeric (octal) notation
Each permission is assigned a value: r = 4, w = 2, x = 1. These powers of two allow the three permissions for one category of user to be encoded in a single octal digit (0–7) by summing the values:
| Octal | Binary | Symbolic | Meaning |
|---|---|---|---|
| 0 | 000 | --- | no permissions |
| 1 | 001 | --x | execute only |
| 2 | 010 | -w- | write only |
| 3 | 011 | -wx | write and execute |
| 4 | 100 | r-- | read only |
| 5 | 101 | r-x | read and execute |
| 6 | 110 | rw- | read and write |
| 7 | 111 | rwx | read, write, and execute |
A complete mode is three octal digits: owner, group, others. For example:
-
644— owner read/write, group read, others read. The default for most files. Verbose form:rw-r--r--. -
600— owner read/write, no one else anything. Typical for private files like SSH keys. Verbose form:rw-------. -
755— owner read/write/execute, group and others read/execute. Typical for executables and public directories. Verbose form:rwxr-xr-x. -
700— owner full, nobody else anything. Typical for private directories. Verbose form:rwx------. -
777— everyone full. Very permissive; almost never appropriate on a multi-user system.
4.5 Changing permissions with chmod
chmod changes a file's mode. It accepts two
notations: symbolic and octal.
Symbolic notation
chmod [ugoa][+-=][rwxXst] file...
-
Who:
u(user/owner),g(group),o(others),a(all three). If omitted,ais assumed, modified by the umask (see §4.6). -
Operation:
+(add),-(remove),=(set exactly, clearing the other bits). -
Permissions:
r,w,x. Additional letters for the special bits:s(setuid/setgid),t(sticky). The uppercaseXmeans "execute only if the file is a directory or already has execute for someone".
# Add execute for the owner
$ chmod u+x script.sh
# Add read for the group and remove write for others
$ chmod g+r,o-w file.txt
# Set exactly rw- for the owner, r-- for group and others
$ chmod u=rw,go=r file.txt
# Grant the whole world read/execute on a directory
$ chmod a+rx public/
# Remove all permissions for the group and others
$ chmod go= secret.txt
Octal notation
# Set owner rwx, group rx, others rx
$ chmod 755 script.sh
# Set owner rw only
$ chmod 600 private.key
# Set owner rwx, group rwx, others ---
$ chmod 770 shared/
Octal notation sets the mode exactly: the new mode is precisely
the three digits specified, and any bits not mentioned are
cleared. Symbolic notation is relative (add or remove), except
for =, which sets exactly.
Recursive changes
# Change every file and subdirectory in a tree
$ chmod -R u+rwX,go-rwx project/
The -R flag applies the change recursively. The
uppercase X in the permissions list is a useful
refinement: it grants execute permission only to files that
already have execute for someone, or to directories. This
avoids accidentally making every text file executable when
applying a recursive change.
4.6 The umask
When you create a new file or directory, the kernel assigns it a default mode. The exact bits depend on two things: a base mode that is compiled into the system (666 for files, 777 for directories) and the process's umask, a value that is subtracted (via bitwise AND with the complement) from the base mode.
# Show the current umask
$ umask
0022
# Show the umask in symbolic form
$ umask -S
u=rwx,g=rx,o=rx
With a umask of 022:
-
New files are created with mode
666 & ~022 = 644(rw-r--r--). -
New directories are created with mode
777 & ~022 = 755(rwxr-xr-x).
A more restrictive umask of 077:
-
New files:
666 & ~077 = 600(rw-------). -
New directories:
777 & ~077 = 700(rwx------).
The umask is set per process and inherited by child processes.
You typically set it in your shell's startup file
(~/.bashrc or ~/.profile) or
system-wide in /etc/profile or
/etc/login.defs.
Common umask values
022 — the default on most systems. Files are
readable by everyone, writable only by the owner.
027 — files readable by the owner's group only,
used on servers where coworkers may share data.
077 — files readable only by the owner, used on
multi-user systems for users who want strict privacy. In
hardened environments, a umask of 027 or
077 is often the standard.
4.7 Ownership
Every file has an owner (a UID) and a group (a GID). Both are independent of the permission bits: the permission bits specify what the owner and group may do, and the ownership fields say who the owner and group are.
Changing ownership
# Change the owner
$ sudo chown alice file.txt
# Change the owner and group together
$ sudo chown alice:developers file.txt
# Change only the group
$ sudo chgrp developers file.txt
# Or, using chown with a colon but no owner
$ sudo chown :developers file.txt
# Change recursively
$ sudo chown -R alice:developers project/
Changing a file's owner requires root privileges (or
CAP_CHOWN). Changing the group is permitted if you
own the file and are a member of the target group;
otherwise it also requires root.
chown clears setuid and setgid
When you change the owner of a file that has the setuid or setgid bit set, the kernel clears those bits. This is a security measure: without it, an attacker who could change ownership could create a setuid-root binary from an ordinary one. You will need to re-set the setuid bit explicitly if you actually want it (and usually you should not).
4.8 The three special permission bits
In addition to the nine ordinary permission bits, three special bits modify a file's behaviour.
setuid (SUID)
When set on an executable, the program runs with the effective
UID of the file's owner instead of the calling user. Displayed
as an s in the owner's execute slot
(rwsr-xr-x) or an S if execute is also
clear.
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 ... /usr/bin/passwd
The passwd program needs to write to
/etc/shadow, which is writable only by root. The
setuid bit lets any user run passwd and have it
temporarily assume root's privileges to perform the update.
setgid (SGID)
On an executable, setgid makes the program run with the
effective GID of the file's group. On a directory, setgid
causes new files and subdirectories to inherit the directory's
group. Displayed as an s in the group's execute
slot (rwxrwsr-x).
# setgid on a directory: new files inherit the group
$ ls -ld /srv/projectx
drwxrwsr-x 2 root projectx 4096 ... /srv/projectx
The setgid bit on a directory was covered in Lesson 2.3 — it is the mechanism that makes shared project directories work. Every file created inside inherits the directory's group, so access can be governed by group membership.
sticky bit
On a directory, the sticky bit restricts deletion: a file
inside the directory can only be deleted or renamed by its
owner, the directory's owner, or root. Displayed as a
t in the others' execute slot
(rwxrwxrwt).
$ ls -ld /tmp
drwxrwxrwt 15 root root 4096 ... /tmp
The /tmp directory is the classic example. It is
world-writable, so any user can create a temporary file there,
but the sticky bit ensures that user A cannot delete user B's
files. Without the sticky bit, world-writable directories
would allow any user to destroy any other user's data.
Setting the special bits
# Symbolic
$ chmod u+s program # setuid
$ chmod g+s directory # setgid
$ chmod +t directory # sticky
# Octal (the leading digit)
$ chmod 4755 program # setuid + rwxr-xr-x
$ chmod 2755 directory # setgid + rwxr-xr-x
$ chmod 1777 directory # sticky + rwxrwxrwx
4.9 Access checking by the kernel
When a process attempts to open a file for reading, the kernel performs the following checks, in order:
- Is the process's effective UID 0 (root)? If so, most checks are bypassed. (Root can read and write any file. Execute permission is still required for a file to be run as a program, however.)
- Does the process's effective UID match the file's owner? If so, the owner's permission bits apply.
- Does the process's effective GID, or any of its supplementary GIDs, match the file's group? If so, the group's permission bits apply.
- Otherwise, the others' permission bits apply.
Only the first matching category is considered. If the owner's
bits deny access, the group and others' bits are not
consulted — even if they would permit it. This is why a file
with mode 000 owned by user A is inaccessible
even to a member of the file's group, if that member happens
to be the owner.
The check is enforced on every open, every read, every write, and every execute. On directories, it is enforced on every path component that is traversed.
4.10 Security implications
The permission model is small but has a range of security implications that are worth understanding.
Over-permissive files
A file with mode 777 is writable by anyone.
If it is a script that gets run by a privileged user, an
attacker can modify it and gain that user's privileges the
next time it runs. World-writable files are a common
source of privilege escalation.
Wrong ownership
A file that should be owned by root but is owned by an ordinary user can be modified by that user. If it is referenced in a privileged context, that is a vulnerability. System files should be owned by root and not writable by non-root users.
Directory execute bits
Execute permission on a directory is required to traverse
it. A directory with mode rw- lets you list
its contents but not access files inside. A directory with
mode --x lets you access files if you know
their names, but not list them. Neither is a strong
barrier against an attacker who can guess filenames.
Setuid surprises
Every setuid-root binary on a system is a potential privilege-escalation target. Modern practice minimises the number of setuid binaries and replaces them with capabilities (Lesson 12.5) where possible.
Umask defaults
A permissive umask creates files that may leak information
to other users. On a shared system, use 027 or
077. On a personal laptop, 022 is
often acceptable.
Recursive chmod
chmod -R 777 directory is a common mistake. It
makes everything in the tree world-writable, including
files that should not be. This one command has caused
countless security incidents.
4.11 Applying least privilege
The principle of least privilege — every program and user should operate with the fewest privileges necessary — translates directly into permission choices:
-
Start restrictive, widen as needed. When
creating a file, use the most restrictive mode that still
lets the intended users do their work. Modes
600,640, and660are usually sufficient. -
Avoid 777 and 666. World-writable files are
rarely necessary on a modern system. When a shared resource
needs to be writable by multiple users, use a dedicated group
and mode
775or770instead of777. -
Set a sensible umask. On a multi-user
system, use
027at minimum. Users who handle sensitive data can set077. - Own system files correctly. Configuration and binaries should be owned by root. Log files should be owned by the service that writes them. Data files should be owned by the user who produces them.
-
Audit periodically. Use
findto locate files with unexpected permissions or ownership:# World-writable files find / -perm -0002 -type f 2>/dev/null # Files owned by non-root in /etc find /etc -not -user root 2>/dev/null # setuid and setgid binaries find / -perm -6000 -type f 2>/dev/null -
Use capabilities instead of setuid where possible.
A program that needs to bind to a low-numbered port should
have
CAP_NET_BIND_SERVICE, not the setuid bit. Detailed in Lesson 12.5. - Prefer groups to world access. If a resource needs to be shared by a team, create a group and give the resource group ownership. Avoid opening access to "others" unless the resource is genuinely public.
4.12 Beyond the classical model: ACLs
The nine-bit model has a limitation: it only expresses permissions for one owner, one group, and everyone else. For a file that needs to be readable by user A, writable by user B, and inaccessible to everyone else, there is no clean way to express this with the classical bits.
POSIX Access Control Lists (ACLs) extend the model to allow per-user and per-group entries beyond the owner/group/others triad. They are supported by ext4, XFS, Btrfs, and other modern file systems, and they are enabled by default on most distributions.
# Show the ACL on a file
$ getfacl report.txt
# file: report.txt
# owner: alice
# group: developers
user::rw-
user:bob:r-- # extra entry: bob can read
group::r--
mask::r--
other::---
# Add a read permission for bob
$ setfacl -m u:bob:r report.txt
# Add read+write for a group
$ setfacl -m g:auditors:rw report.txt
# Remove the ACL entry for bob
$ setfacl -x u:bob report.txt
# Remove all extended ACLs (leave only the base permissions)
$ setfacl -b report.txt
When a file has an ACL, ls -l displays a
+ at the end of the mode field to signal this.
The ACL "mask" entry is a subtlety: it acts as an upper bound
on the permissions granted by named user, named group, and
group entries, and it is what chmod modifies when
applied to a file with an ACL.
ACLs are useful but they add complexity: the file's true access
policy is no longer visible in a single ls -l, and
chmod no longer sets the whole policy. For most
files, the classical bits suffice; for files that need
finer-grained access, ACLs are the standard tool.
4.13 What follows from this
The permission model established in this lesson is what makes multi-user Linux possible: it is the mechanism by which isolation between users is enforced, the means by which services are confined to their own data, and the foundation on which the more elaborate security mechanisms of Module 5 are built. Understanding it in detail is a prerequisite for everything that follows — from setting up the development environment in the next lesson to reasoning about security boundaries in Unit 12.
05 Worked example
To make the permission model concrete, let's walk through a realistic scenario: setting up the file permissions for a small web application deployment.
Setting permissions for a web application
A web application has the following files:
/srv/webapp/
├── config/
│ ├── database.conf # contains credentials
│ └── app.conf # application settings
├── logs/
│ └── app.log # application log
├── public/
│ └── index.html # served to the public
└── bin/
└── start.sh # startup script
The application runs as the webapp user, and it
is administered by the webteam group. We want:
-
database.confreadable only bywebapp, because it contains secrets. -
app.confreadable bywebappand thewebteamadministrators, writable only bywebapp. -
logs/writable bywebappand readable bywebteamfor troubleshooting. -
public/readable by everyone, so the web server can serve it, and writable only by administrators. -
start.shexecutable by thewebappuser.
Applying the permissions:
# Set the base ownership: everything to webapp, group webteam
$ sudo chown -R webapp:webteam /srv/webapp
# Database config: owner (webapp) read only
$ sudo chmod 400 /srv/webapp/config/database.conf
$ ls -l /srv/webapp/config/database.conf
-r-------- 1 webapp webteam 128 Oct 15 12:00 database.conf
# App config: owner read/write, group read
$ sudo chmod 640 /srv/webapp/config/app.conf
$ ls -l /srv/webapp/config/app.conf
-rw-r----- 1 webapp webteam 512 Oct 15 12:00 app.conf
# Logs directory: owner read/write/execute, group read/execute
$ sudo chmod 750 /srv/webapp/logs
$ ls -ld /srv/webapp/logs
drwxr-x--- 2 webapp webteam 4096 Oct 15 12:00 logs
# Public directory: world read/execute, owner (webapp) full
$ sudo chmod 755 /srv/webapp/public
$ ls -ld /srv/webapp/public
drwxr-xr-x 2 webapp webteam 4096 Oct 15 12:00 public
# Public HTML file: world readable
$ sudo chmod 644 /srv/webapp/public/index.html
$ ls -l /srv/webapp/public/index.html
-rw-r--r-- 1 webapp webteam 1024 Oct 15 12:00 index.html
# Startup script: owner read/write/execute
$ sudo chmod 700 /srv/webapp/bin/start.sh
$ ls -l /srv/webapp/bin/start.sh
-rwx------ 1 webapp webteam 256 Oct 15 12:00 start.sh
Let's verify the effect from three different perspectives:
As a member of webteam (an administrator):
$ id alice
uid=1002(alice) gid=1002(alice) groups=1002(alice),2000(webteam)
$ cat /srv/webapp/config/database.conf
cat: /srv/webapp/config/database.conf: Permission denied
# denied — the file is 400 and alice is not the owner
$ cat /srv/webapp/config/app.conf
# succeeds — alice is in webteam, group bit is r--
$ tail /srv/webapp/logs/app.log
# succeeds — logs directory is 750, group has r-x
$ ./srv/webapp/bin/start.sh
bash: /srv/webapp/bin/start.sh: Permission denied
# denied — the file is 700 and alice is not the owner
As the webapp user (the application):
$ sudo -u webapp cat /srv/webapp/config/database.conf
# succeeds — webapp is the owner, owner bit is r--
$ sudo -u webapp cat /srv/webapp/config/app.conf
# succeeds — webapp is the owner, owner bits are rw-
$ sudo -u webapp ./srv/webapp/bin/start.sh
# succeeds — webapp is the owner, owner bit is rwx
As a random user (not in webteam):
$ id carol
uid=1003(carol) gid=1003(carol) groups=1003(carol)
$ cat /srv/webapp/config/app.conf
cat: /srv/webapp/config/app.conf: Permission denied
# denied — carol is not the owner and not in webteam
$ ls /srv/webapp/public/
index.html
# succeeds — public is world-readable
$ cat /srv/webapp/public/index.html
# succeeds — world-readable
$ cat /srv/webapp/logs/app.log
cat: /srv/webapp/logs/app.log: Permission denied
# denied — carol is not the owner and not in webteam
Notice that the "public" directory is world-readable and
world-executable, but its parent directories are not:
/srv/webapp itself is 750, meaning
that a user like carol cannot traverse into it. If we wanted
the public directory to actually be publicly accessible, we
would need to make the parent directory world-executable
too — or restructure the layout so that the public content
lives outside the private tree.
The lesson: permissions are not just about
individual files. The whole path matters. A restrictive
parent directory overrides permissive permissions on a child.
When setting up a directory tree, it is worth walking through
the path from / to each file and checking every
component — exactly as the kernel does when it resolves a
path.
06 Interactive activity
Activity · experiment with permissions on your VM
Open a terminal and run the following. Record what you observe
for each step. Some of the exercises require a second user
account; if you do not have one, use su - or
sudo -u to switch to a system account (for
example, nobody).
-
Create a test file and inspect its mode.
What is the mode? What does it correspond to in octal? What is the umask that produced it?touch test.txt ls -l test.txt -
Change the mode with symbolic notation.
What is the mode after each step? Confirm your predictions by translating the symbolic change to the resulting bits.chmod u+x test.txt ls -l test.txt chmod g-w test.txt ls -l test.txt chmod o-r test.txt ls -l test.txt -
Set an exact mode with octal notation.
Trychmod 640 test.txt ls -l test.txt chmod 755 test.txt ls -l test.txt chmod 000 test.txt ls -l test.txtcat test.txtafter the final command. What happens? Can you restore access? -
Test the umask.
What mode does each file and directory have? Confirm that the mode matches what the formulaumask 077 touch private.txt mkdir private-dir ls -l private.txt private-dir umask 022 touch default.txt mkdir default-dir ls -l default.txt default-dirbase & ~umaskpredicts. -
Explore the special bits.
Create a script, then observe what happens when you run it
with and without the execute bit:
Then examine the sticky bit onecho 'echo hello' > script.sh ./script.sh chmod +x script.sh ./script.sh/tmp:
Can you see the effect of the sticky bit by checking whether another user could delete your file?ls -ld /tmp touch /tmp/myfile-$$ ls -l /tmp/myfile-* -
Test ownership with a second user. If you
have a second account, log in as that user and try to read
a file you own. Which permissions mattered?
# As user1 echo "secret" > /tmp/shared.txt chmod 600 /tmp/shared.txt # As user2 (switch with su or sudo -u) cat /tmp/shared.txt # denied # Back as user1: allow read for others chmod o+r /tmp/shared.txt # As user2 again cat /tmp/shared.txt # succeeds -
Audit your system.
Run the three audit commands from section 4.11:
What did you find? Are any of the results surprising?# World-writable files sudo find / -perm -0002 -type f 2>/dev/null | head -10 # setuid and setgid binaries sudo find / -perm -6000 -type f 2>/dev/null | head -20 # Files in /etc not owned by root sudo find /etc -not -user root 2>/dev/null
Reflect: which of these experiments best illustrated the difference between the classical permission model and your mental model before the lesson? Which commands are you most likely to actually use in practice?
07 Knowledge check
Check your understanding
Question 1
A file has mode 754. What can the owner do?
The group? Others?
Show answer
754 in octal is rwxr-xr-- in
symbolic form. The owner can read, write, and execute
(7 = rwx). The group can read and execute (5 = r-x) but
not write. Others can read only (4 = r--) and cannot
write or execute. This is a typical mode for an executable
that should be readable by everyone but writable only by
its owner.
Question 2
What is the difference between the r, w, and x permissions on a file versus on a directory?
Show answer
r allows reading
the file's contents, w allows modifying its
contents, and x allows executing it as a
program. On a directory: r
allows listing the names of entries in the directory,
w allows creating, renaming, and deleting
entries within the directory, and x allows
traversing the directory — that is, using it as a
component in a path to access files inside. The
distinction is important because the permissions on a
file's directory determine whether the file can be found
at all, while the permissions on the file itself
determine what can be done with it once found.
Question 3
What does the umask 027 produce for a new file
and a new directory? Show your work.
Show answer
~027 = 750 in octal.
For a file:
666 & 750 = 640, which is
rw-r----- — the owner can read and write,
the group can read, and others have no access.
For a directory:
777 & 750 = 750, which
is rwxr-x--- — the owner has full access,
the group can read and traverse, and others have no
access.
A umask of 027 is common on servers where files should be readable within a group but not to the wider world.
Question 4
Explain the difference between the setuid and setgid bits, and describe one classic use of each.
Show answer
/usr/bin/passwd, which must write to
/etc/shadow — a file writable only by root
— and so is setuid root. The setgid bit
on an executable causes the program to run with the
effective GID of the file's group; on a directory, it
causes new files and subdirectories to inherit the
directory's group. The classic use of setgid on a
directory is a shared project folder: making the
directory setgid ensures all files created inside belong
to the project's group, so group permissions can be used
to grant access to all project members.
Question 5
Why is chmod -R 777 directory considered a
security mistake?
Show answer
chmod -R 777 makes every file and
subdirectory in the tree world-readable, world-writable,
and world-executable. Any user on the system can modify
any file, replace any file, or add executable content.
If the directory contains scripts that will be run by a
privileged user, an attacker can modify those scripts
and gain the privileged user's access the next time they
run. Even in the absence of a privileged context,
777 on the whole tree allows any user to
destroy any other user's work. The correct approach is
to use the minimum permissions that the intended users
need — typically 755 for directories and
644 for files, or a group-based scheme with
750/640 for shared resources
that should not be world-accessible.
08 Unit discussion
Discussion prompt
The classical UNIX permission model has three categories (owner, group, others) and three permissions (read, write, execute). This is compact and easy to reason about, but it is also coarse: it cannot express "user A may read, user B may write, user C may execute" without resorting to ACLs or more elaborate mechanisms. Some systems have responded by moving away from the UNIX model entirely — Windows uses a rich ACL model by default, and modern cloud platforms use IAM policies that are even more expressive.
Is the classical UNIX permission model still the right foundation for a modern operating system, or has it been outgrown? Argue for whichever view you find more persuasive. Consider the trade-offs: expressiveness versus simplicity, learnability versus precision, and the historical fact that most UNIX-like systems have managed with the nine-bit model for fifty years.
Post your response to the Unit 2 discussion forum and reply to at least two classmates. This activity supports CLO6 and CLO7.
09 Practice exercise
This ungraded exercise consolidates the lesson. Aim to spend about 45–60 minutes on it.
-
Complete the octal table. Without looking
at the table in section 4.4, write out the octal value for
each of these symbolic modes:
rwx,rw-,r-x,r--,-wx,-w-,--x,---. Then check your answers. -
Build a directory with specific permissions.
Create the following structure and set the permissions as
shown:
Verify the mode of each entry withsandbox/ ├── private/ (700) │ └── secret.txt (600) ├── team/ (770, setgid) │ └── shared.txt (660) └── public/ (755) └── readme.txt (644)ls -ldandls -l. Confirm that the setgid directory makes new files inherit the directory's group. -
Test the umask. Set the umask to
077, create a file and a directory, and note the resulting modes. Then set the umask to000and repeat. Then022and repeat. Confirm that each mode matches the formula in section 4.6. -
Write a script to audit permissions.
Write a shell script that takes a directory as an argument
and lists every file inside it whose mode is more permissive
than
644for regular files or more permissive than755for directories. Print the file path and its current mode. -
Investigate the special bits. Find three
setuid binaries on your system (use
find / -perm -4000). For each, look up what the binary does and explain in one sentence why it needs setuid. What would happen if the setuid bit were removed? -
Explore ACLs. Create a file owned by you,
then use
setfaclto grant read access to another user on the system. Verify withgetfacland by trying to read the file as that user. Then remove the ACL entry withsetfacl -xand verify that access has been revoked. - Reflect. In your own words, explain why "delete a file" requires write permission on the directory rather than on the file. Give a concrete example of a scenario where this distinction matters.
10 Summary
- Every file has a nine-bit permission mode: three permissions (read, write, execute) for three categories (owner, group, others).
-
For a file,
r,w, andxcontrol reading, modifying, and executing the file. For a directory, they control listing the names, creating or removing entries, and traversing the directory. -
Permissions can be expressed in symbolic form
(
rwxr-xr-x) or octal form (755). The mapping isr=4,w=2,x=1. -
chmodchanges permissions;chownandchgrpchange ownership and group. Ownership changes require root privileges (or appropriate capabilities). -
The umask determines the default mode of
newly created files and directories. Common values are
022,027, and077. - Three special bits modify file behaviour: setuid makes a binary run with the owner's privileges, setgid makes it run with the group's privileges (or, on a directory, causes new files to inherit the directory's group), and the sticky bit on a directory restricts deletion to the file's owner.
- The kernel checks permissions on every access, using the first matching category (owner, then group, then others).
-
Least privilege means using the most restrictive permissions
that still let the intended users do their work. Avoid
777, audit for unexpected permissions, and use capabilities instead of setuid where possible. - POSIX ACLs extend the classical model with per-user and per-group entries, at the cost of additional complexity.
Looking ahead
Lesson 2.5 closes Unit 2 by turning to the development environment: the compilers, build tools, version control, and debuggers that every subsequent laboratory will assume. The shell, user, and permission skills from this unit are all prerequisites for that material.
11 References
- Stevens, W. R., & Rago, S. A. Advanced Programming in the UNIX Environment, 3rd ed., Sections 4.4–4.7. Addison-Wesley, 2013.
- Nemeth, E., Snyder, G., Whaley, B., & Mackin, D. UNIX and Linux System Administration Handbook, 5th ed., Chapter 8. Addison-Wesley, 2017.
- Shotts, W. The Linux Command Line, 5th ed., Chapter 9 (permissions). No Starch Press, 2019.
-
Linux man pages:
man 1 chmod,man 1 chown,man 1 chgrp,man 1 umask,man 2 chmod,man 2 access,man 5 acl,man 1 getfacl,man 1 setfacl. - POSIX.1-2017 / IEEE Std 1003.1, Standard for Information Technology — Portable Operating System Interface (POSIX), Section on file access permissions.