skip to content

Permissions and Users

The Unix permission model: rwx bits and their octal shorthand, setuid/setgid/sticky, ACLs, the account files behind users and groups, and sudoers. Expect to be asked what 4755 means and why a setuid binary deserves suspicion.

part ofLinux & distributionsoverview, primer and where to startread it →
on this pageshow

questions

page 1 of 2

On Linux, how do capabilities split up root's privilege, and which capability lets a process that is not running as root bind a socket to TCP port 80?

level: juniorimportance: must knowfreq 72%

answer

  1. root's power, sliced into pieces
  2. one named privilege per kernel operation
  3. ports under 1024 are the reserved range
  4. the capability name mentions binding a service
  5. setcap ... =+ep on the binary

basics

~20 s

Linux capabilities break root's all-or-nothing power into more than forty independent privileges that can be granted to a process or an executable one at a time. CAP_NET_BIND_SERVICE is the one that allows binding to ports below 1024.

solid answer

~50 s

Classic Unix has one privilege bit: UID 0 skips almost every kernel permission check and every other UID skips none. Linux capabilities slice that single bit into separate privileges — over forty of them — so a process can hold exactly the one kernel operation it needs and nothing else. Binding an Internet-domain socket to a port below 1024 is gated by `CAP_NET_BIND_SERVICE`, so a web server can listen on 80 or 443 as an ordinary user account. You attach it to the executable with `setcap cap_net_bind_service=+ep /path/to/binary`, or a supervising process can pass it down through the ambient set. It grants nothing else: raw sockets still need `CAP_NET_RAW`, and changing addresses, routes or firewall rules still needs `CAP_NET_ADMIN`. On modern kernels you can also lower the privileged-port boundary itself with the `net.ipv4.ip_unprivileged_port_start` sysctl instead of granting anything.

code

bash · 4 lines
bash
sudo setcap cap_net_bind_service=+ep /usr/local/bin/api
getcap /usr/local/bin/api
sudo -u nobody /usr/local/bin/api &
grep ^Cap /proc/$(pgrep -n -f /usr/local/bin/api)/status

go deeper

for a junior

Know that ports below 1024 are reserved by the kernel and that CAP_NET_BIND_SERVICE is what lets a non-root process bind them. Be able to say that capabilities are root's power split into separate pieces.

for a middle

Explain the two ways a process obtains the capability — an attribute on the executable set by setcap, or inheritance from a privileged parent — and name the neighbouring network capabilities it does not include.

for a senior

Show you can verify the claim on a live host by reading the capability masks of the running process, and weigh the per-binary grant against lowering net.ipv4.ip_unprivileged_port_start or fronting the service with a proxy.

for a principal

Own the policy question: which capabilities you are willing to hand out at all, who is allowed to run setcap on the fleet, and whether a host-wide sysctl change is an acceptable trade for removing a per-binary privilege.

## The problem capabilities solve In traditional Unix, privilege is a single boolean. A process whose effective UID is 0 bypasses essentially every permission check the kernel makes; a process with any other UID bypasses none of them. That forces a bad bargain: a program that needs one privileged operation — listening on port 80, changing the system clock, opening a raw socket — has to run as root, and therefore also gets the ability to read `/etc/shadow`, load kernel modules, kill any process and rewrite any file. If it is compromised, the attacker inherits all of it. Linux capabilities (introduced in 2.2 and reworked repeatedly since) break that boolean into independent, individually grantable privileges. Internally, each privileged code path in the kernel calls a check for one specific capability rather than asking "is this UID 0?". Current kernels define more than forty of them, each named `CAP_*`. ## What CAP_NET_BIND_SERVICE actually grants The kernel reserves ports below 1024 — the "privileged" or "well-known" ports — so that an arbitrary local user cannot start a fake SSH or HTTP service on a port clients trust. `CAP_NET_BIND_SERVICE` is the capability that lifts exactly that restriction: a thread holding it may bind an Internet-domain socket to a port in that range. It is worth being precise about what it does *not* grant. It does not allow opening raw or packet sockets (that is `CAP_NET_RAW`, what `ping` and `tcpdump` need). It does not allow configuring interfaces, routes, or netfilter rules (that is `CAP_NET_ADMIN`). It has nothing to do with file permissions. This narrowness is the whole point of the model. ## Where a process's capability comes from There are two practical sources. The first is the executable file. `setcap` stores a capability set on the binary, and the kernel grants it at `execve()` time regardless of who runs the program: ``` sudo setcap cap_net_bind_service=+ep /usr/local/bin/api getcap /usr/local/bin/api # /usr/local/bin/api cap_net_bind_service=ep ``` The `p` means the capability lands in the process's permitted set and `e` means it is also made effective immediately, which is what a program that is not capability-aware needs. The second is inheritance from the parent. A service manager or supervisor that itself holds the capability can arrange for the child to keep it across `exec` through the ambient set, which is how service managers grant a low port without touching the binary on disk. ## Reading what a running process holds Every thread's sets are exposed as hex bitmasks in `/proc/<pid>/status`: ``` grep ^Cap /proc/self/status # CapInh: 0000000000000000 # CapPrm: 0000000000000000 # CapEff: 0000000000000000 # CapBnd: 000001ffffffffff # CapAmb: 0000000000000000 ``` `capsh --decode=0000000000000400` turns a mask into names — bit 10 is `cap_net_bind_service`. `getpcaps <pid>` prints the same information in readable form. ## The alternative: move the boundary instead The 1024 cutoff is a kernel policy, not a law. Since Linux 4.11 the sysctl `net.ipv4.ip_unprivileged_port_start` controls where the privileged range ends; it defaults to 1024, and setting it to 80 lets *any* local process bind 80 and above with no capability at all. That is convenient and sometimes the right answer for a single-purpose host, but it is a system-wide loosening: every local user gains the ability to squat on those ports, so it trades a per-binary grant for a host-wide one. ## Why "non-root plus a capability" is not automatically safe Capabilities are only least privilege if the capability you pick is actually small. `CAP_NET_BIND_SERVICE` genuinely is. Others — `CAP_SYS_ADMIN`, `CAP_SYS_MODULE`, `CAP_SETUID`, `CAP_DAC_OVERRIDE` — let a holder recover full root by a short path, so "we run as UID 1000 with a capability" tells you nothing on its own until you know which capability. And nothing about holding a capability restricts the ordinary things the process could already do: it still reads every world-readable file, opens outbound connections and executes other programs under the normal permission rules.

  • Apart from granting the capability, what other ways are there to get a service listening on port 80 as an unprivileged user?
    Lower the kernel's boundary with the `net.ipv4.ip_unprivileged_port_start` sysctl, which is host-wide and lets any local user bind those ports. Or have something privileged own the port and hand the traffic over: a reverse proxy in front of a high-port backend, or a supervisor that opens the listening socket itself and passes the file descriptor to the unprivileged process at start-up.
  • Does CAP_NET_BIND_SERVICE let the process do anything else on the network?
    No. It gates exactly one check — binding an Internet-domain socket to a port below 1024. Raw and packet sockets require `CAP_NET_RAW`; configuring addresses, routes, interfaces or netfilter rules requires `CAP_NET_ADMIN`. That narrowness is why it is one of the few capabilities that is genuinely safe to hand out.
  • An older service binds port 80 as root and then drops to an unprivileged user itself. Is a capability still needed?
    No. The capability check happens once, at `bind()`. A process that starts privileged, binds, and then drops its UID keeps the open listening socket afterwards. The downside is that the code path before the drop still runs with full root, and getting the drop wrong — forgetting supplementary groups, or a `setuid` call whose return value is ignored — is a classic source of privilege-escalation bugs.

Root is a master key that opens every door in the building. Capabilities are the key ring where each door has its own key, so the night cleaner can be handed only the one for the lobby.

saying these in an interview costs you the question

  • Capabilities are just sudo rules under a different name
  • A non-root process is safe whatever capability it holds
  • Ports below 1024 are blocked by the firewall
  • CAP_NET_BIND_SERVICE also allows sniffing traffic
  • Making the binary executable is enough to bind port 80

context

open as a page

On a RHEL host, what is the difference between SELinux running in enforcing mode, permissive mode, and being disabled, and why is `setenforce 0` not the same as setting SELINUX=disabled in /etc/selinux/config?

level: juniorimportance: must knowfreq 70%

basics

~20 s

Enforcing blocks policy violations and logs them. Permissive blocks nothing but still logs every would-be denial. Disabled loads no policy and stops maintaining file labels. setenforce 0 switches to permissive only until reboot; /etc/selinux/config sets the mode chosen at boot.

open as a page

On Linux, `ls -l` prints a file's mode as a string such as `-rw-r--r--`. Explain what each part of that string means and what the equivalent octal number is.

level: juniorimportance: must knowfreq 82%

basics

~20 s

The first character gives the file type; the next nine are three rwx triads for owner, group and others. So -rw-r--r-- is a regular file the owner can read and write while everyone else can only read: octal 644.

open as a page

On a Linux system, what does each of /etc/passwd, /etc/shadow and /etc/group hold, and why was the password hash moved out of /etc/passwd?

level: juniorimportance: must knowfreq 74%

basics

~20 s

/etc/passwd holds one line per account — name, UID, primary GID, real name, home directory and login shell — and is world-readable. /etc/shadow holds the password hashes and ageing fields, readable only by root. /etc/group lists groups and their extra members.

open as a page

You grant a named user write access to a file with `setfacl`, but `getfacl` prints `#effective:r--` beside that entry and the user still cannot write. What is the POSIX ACL mask, and what typically leaves it too restrictive?

level: middleimportance: must knowfreq 48%

basics

~20 s

The mask entry is an upper bound on every named user, named group and the owning group; rights above it are granted but not effective. It is most often narrowed by a later chmod, because on an ACL-bearing file the group-class mode bits map to the mask, not to the owning group.

open as a page

A daemon on a RHEL host is refused access to a file that it owns and that is mode 0644, and `chmod 777` on the file changes nothing. Which access-control layer is denying it, and how does a process's domain and a file's type produce that decision?

level: middleimportance: must knowfreq 62%

basics

~20 s

SELinux is denying it. Traditional owner/mode checks run first and already passed, so loosening them cannot help. SELinux then compares the process's domain label with the file's type label against the loaded policy, and refuses because no rule allows that pair.

open as a page

On Linux, what does the execute bit mean on a directory as opposed to on a regular file, and what can someone do with a directory that has x but not r?

level: middleimportance: must knowfreq 62%

basics

~20 s

On a directory the execute bit means search, not run: it permits resolving a name inside the directory. Read permits listing the names. With x but no r you can open a file whose exact name you already know, but ls fails.

open as a page

On Linux, `/usr/bin/passwd` is owned by root with mode `-rwsr-xr-x`, yet any user may run it to change their own password. What does that `s` cause the kernel to do at exec time, and how do the process's real, effective and saved user IDs differ afterwards?

level: middleimportance: must knowfreq 74%

basics

~20 s

The set-user-ID bit makes the kernel set the new process's effective UID to the file owner's UID at exec time. So passwd runs with root's effective identity and can update the shadow file, while the real UID still records who launched it.

open as a page

After running `usermod -aG deploy alice` on a Linux host, Alice's already-open shell still cannot read the deploy group's files until she logs out and back in. Why, and what would happen if the `-a` had been omitted?

level: middleimportance: must knowfreq 64%

basics

~20 s

A process's group list is part of its kernel credentials, fixed when the login session was created and inherited by every child. Editing /etc/group changes the database, not a running process, so a new login is needed. Omitting -a replaces all supplementary groups instead of adding one.

open as a page

Standard Linux file permissions describe only the owner, the owning group and everyone else. What do POSIX ACLs add on top of that model, and how can you tell from `ls -l` output that a file carries one?

level: juniorimportance: should knowfreq 52%

basics

~20 s

POSIX ACLs extend Unix permissions with entries for individually named users and groups, so one person can be granted rights on a file without changing its owner or the group everyone belongs to. In ls -l, a trailing plus sign after the mode marks such a file.

open as a page

On a Linux host, `ls -ld /tmp` prints `drwxrwxrwt`. What does that trailing `t` do, and why is it needed on a world-writable directory?

level: juniorimportance: should knowfreq 62%

basics

~20 s

The trailing t is the sticky bit, also called the restricted-deletion flag. On a world-writable directory it still lets anyone create files, but only a file's owner, the directory's owner, or root may rename or delete an entry.

open as a page

A shared directory carries an ACL granting a named group write access, yet files newly created inside it do not get that access. How do POSIX default ACLs work, and what determines the permissions of a file created in such a directory?

level: middleimportance: should knowfreq 42%

basics

~20 s

An ordinary ACL controls access to the directory itself and is not inherited. Inheritance requires a separate default ACL, set with setfacl -d, which acts as a template copied onto newly created files and subdirectories. When one exists, the process umask is not applied.

open as a page

You run setcap cap_net_bind_service=+ep on /usr/local/bin/api and it binds port 80 correctly. After the release pipeline copies that same binary to another host with tar, the service fails with a permission error on bind. Where did the capability go?

level: middleimportance: should knowfreq 45%

basics

~20 s

File capabilities live in the security.capability extended attribute on the inode, not in the permission bits. Copying, archiving or rebuilding a binary drops that attribute unless extended attributes are explicitly preserved, so setcap has to be re-run on the target host.

open as a page

Ubuntu ships AppArmor and RHEL ships SELinux as their mandatory access control system. What is the fundamental difference in how each one identifies the things it is protecting, and what practical consequences does that difference have?

level: middleimportance: should knowfreq 48%

basics

~20 s

AppArmor mediates by pathname: profiles attach to an executable and list the paths it may touch. SELinux mediates by label: every process and object carries a type stored on the inode, and policy is written over those types. Path-based rules are far easier to read; label-based rules follow the object wherever it goes.

open as a page

You clear an SELinux denial by running `chcon -t httpd_sys_content_t` on a data directory and the service starts working; weeks later, after the machine is relabelled, it breaks again. Where do SELinux file labels live, and what should you have done instead?

level: middleimportance: should knowfreq 52%

basics

~20 s

A label lives in the file's security.selinux extended attribute, and chcon writes it directly. A relabel replays the policy's default-context database, which still says the old type, so it overwrites your change. Record the intent with semanage fcontext, then apply it with restorecon.

open as a page

What does a process's umask do on Linux, and why does a umask of 022 produce new files with mode 644 but new directories with 755?

level: middleimportance: should knowfreq 58%

basics

~20 s

The umask is a per-process mask of permission bits to clear at file creation: the final mode is the requested mode with the mask bits removed. Programs request 0666 for files and 0777 for directories, so a 022 mask leaves 644 and 755.

open as a page

Several engineers share a directory owned by the group `devs`, but files each of them creates come out owned by that person's own primary group, so their colleagues cannot write them. What does setting the set-group-ID bit on the directory change, and what does it deliberately not change?

level: middleimportance: should knowfreq 48%

basics

~20 s

A set-group-ID directory makes new entries inherit the directory's group instead of the creator's primary group, and new subdirectories inherit the bit itself. It changes group ownership only — the permission bits on the new file still come from the creating process.

open as a page

On Linux, what is the practical difference between `su`, `su -`, `sudo -i` and `sudo -s` — which password does each ask for, and what environment does the resulting shell get?

level: middleimportance: should knowfreq 60%

basics

~20 s

su authenticates you as the target user with that user's password; sudo authenticates you as yourself against a policy. The dash forms (su -, sudo -i) start a clean login shell in the target's home; su and sudo -s keep your current directory and much of your environment.

open as a page

After archiving a directory tree with GNU tar and unpacking it on another Linux host, the named-user ACL entries are gone although the ordinary mode bits survived. Where does Linux store POSIX ACLs, and what decides whether they survive a copy or a restore?

level: seniorimportance: should knowfreq 36%

basics

~20 s

POSIX ACLs live in extended attributes on the file, not in the inode mode field, so any tool that copies only mode bits silently drops them. GNU tar needs --acls, rsync needs -A, and the destination filesystem must be able to store extended attributes at all.

open as a page

Hardening guidance often says that granting a Linux process CAP_SYS_ADMIN is close to giving it root outright. Why is that true, and which other capabilities carry the same warning?

level: seniorimportance: should knowfreq 42%

basics

~20 s

CAP_SYS_ADMIN is the kernel's catch-all capability, covering mount and dozens of unrelated administrative operations, and mount alone is enough to take over a system. CAP_SYS_MODULE, CAP_SYS_RAWIO, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_SYS_PTRACE, CAP_SETUID and CAP_SETPCAP are similarly root-equivalent.

open as a page

A process holds CAP_NET_ADMIN in its permitted and inheritable sets and then executes a helper binary that has no file capabilities of its own. Why does the helper start with nothing, and which of the Linux capability sets exists to fix exactly this case?

level: seniorimportance: should knowfreq 38%

basics

~20 s

A thread carries five capability sets: permitted, effective, inheritable, bounding and ambient. Across execve of a file with no capabilities, the inheritable set grants nothing on its own — it must be matched by the file. The ambient set, added in Linux 4.3, is what carries privilege through.

open as a page

A service on a RHEL host is failing and the audit log shows an SELinux AVC denial. Walk through how you decide between correcting a label, flipping a policy boolean, and generating a custom policy module — and say what it could mean when the denial you expect never appears in the log at all.

level: seniorimportance: should knowfreq 50%

basics

~20 s

Read the denial's source context, target context, object class and permission. A wrong target label means relabel it. A supported optional behaviour means set the boolean that enables it. Only a genuinely new access justifies a reviewed custom module. Missing denials usually mean a dontaudit rule is suppressing them.

open as a page

On Linux, why can a regular user not hand one of their own files to another user with `chown`, while they can often change its group with `chgrp`?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Linux restricts changing a file's owner to privileged processes, because giving files away would let users escape disk quotas and dump content into other accounts. Changing the group is allowed to the file's owner, but only to a group they themselves belong to.

open as a page

A developer fixes a permissions problem on a Linux server by running `chmod -R 777` over an application's directory tree. What is wrong with that, and how would you set permissions correctly on a tree that mixes directories and data files?

level: seniorimportance: should knowfreq 45%

basics

~20 s

It makes every file world-writable, so any local process can rewrite the application's code and configuration, and it marks data files executable. It is also destructive: the original per-file modes are gone. Set directories and files separately instead.

open as a page

A vendor package installs a set-user-ID root helper binary under `/opt` on a Linux server. What risk does that single mode bit introduce, and what changes if the filesystem holding it is mounted with the `nosuid` option?

level: seniorimportance: should knowfreq 44%

basics

~20 s

A set-user-ID root binary runs with root's effective identity for every user on the box, so any flaw in it becomes a local root exploit. Mounting its filesystem with nosuid makes the kernel ignore the bit, so the program runs unprivileged instead.

open as a page

You are reviewing a sudoers policy. Explain why a rule that grants NOPASSWD access to a single named command can still amount to full root, and what makes a rule genuinely narrow.

level: seniorimportance: should knowfreq 52%

basics

~20 s

A sudoers rule grants a program, not an outcome. If the program can spawn a shell, run an editor or pager, write to an arbitrary path, or read a file the user controls, the grant becomes full root. Narrow rules pin the absolute path, spell out the arguments, and avoid wildcards.

open as a page

You own a fleet of Linux servers where several teams must operate their own services without being given full root. How would you design the account, group and sudo policy?

level: principalimportance: should knowfreq 36%

basics

~20 s

Back identity centrally, grant privilege to groups rather than named users, express every grant as a narrow reviewed sudoers drop-in shipped by configuration management, reserve passwordless rules for dedicated automation accounts, and keep an audited break-glass path for the day the directory is unreachable.

open as a page

On a RHEL host with SELinux enforcing, a daemon that starts fine on its default port fails to bind after you reconfigure it to listen on port 8081. Why would SELinux be involved in a port bind at all, and what is the correct fix?

level: middleimportance: nice to knowfreq 40%

basics

~20 s

SELinux labels TCP and UDP port numbers with types, just as it labels files, and policy only lets a domain bind ports of the types it is allowed. Port 8081 carries a different type than the daemon's default port, so the bind is refused until you add the label with semanage port.

open as a page

On Linux, a file is owned by user alice and group devs with mode 0466 (r--rw-rw-), and alice is a member of devs. Can alice write to that file, and why?

level: middleimportance: nice to knowfreq 30%

basics

~20 s

No. The kernel picks exactly one permission class and stops: because alice's effective UID owns the file, only the owner triad applies, and that is read-only. The group and other bits are never consulted for her.

open as a page

You run `chmod 4755` on a root-owned shell script, and it still executes with the caller's own privileges rather than root's. Why does Linux ignore the set-user-ID bit here, when it honours it on a compiled binary?

level: middleimportance: nice to knowfreq 34%

basics

~20 s

Linux deliberately ignores set-user-ID and set-group-ID bits on interpreted scripts. The kernel applies them only when exec'ing a real executable image, so the interpreter named on the #! line starts unprivileged and the script runs as the caller.

open as a page

showing 1–30 of 33