Michael Paoli on: UNIX/Linux/BSD/... file permissions
Here's how the permissions work - pay attention, many folks
don't get this (fully) correct! (heck about 50 to 80% or more of most
sysadmin candidates I screen/interview don't get this fully correct!)
-
Not covered here: extended attributes, ACLs, SE Linux,
filesystem mount options (e.g. ro, nosuid, nodev), etc.
-
The permissions are part of a full set of [l]stat/status
information bits on the file (here generally referring to a file of
any type, e.g. a directory is just another type of file (as
is block and character device files, named pipes / FIFOs, symbolic
links, etc.)).
There are 12 bits of permissions data,
logically grouped/used into 4 sets of 3 bits each, each also
corresponding to an octal digit - a customary/historical
representation form.
From Most Significant bit (MSb) (highest) to
Least Significant bit (LSb) (lowest),
the first 3 bits / octal digit
are often referred to as "special" permissions,
the remaining 3 (lower) sets of 3 bits (/ octal digit) each are
typically referred to as "ordinary", "base", or
"basic" permissions.
-
Both historically, and also, these 4 sets of 3 bits each are
usually given/used in octal, so there's a one-to-one correlation
from each set of 3 bits to a specific logical grouping of
permissions - so the octal digits are 0 through 7.
-
So, the sets of 3 bits of those 4 sets
the first set of 3 bits (from MSb end) are "special"
permissions.
Then the remaining after that, from MSb - highest (remaining) to
LSb, each set of 3 bits (octal digit) is respectively the
permissions for
user (the UID that owns the file),
group (the GID that owns the file), and
other (sometimes also called "world") -
which is (kind'a) "everybody else" (I'll describe in more
detail further - notably at least also see the bit about
algorithm). The, respectively,
user, group, and
other sets of 3 bits are
often respectively used/referred to symbolically as u, g, and o, and
often/typically in that order, as that's their MSb to LSb ordering
(also often generally preferably / less confusing to use/display
them in that order - for the mere mortal humans to have a somewhat
easier time of it ... see also algorithm).
-
within each set of 3 bits of ordinary permissions, from MSb to
LSb the bits respectively represent
"read",
"write", and
"execute"
permissions, and likewise symbolically generally r, w, and x are
used to represent those permissions.
One can think of each set of 3 bits as (or translate to/from) octal
digit, weighted as
4 for r,
2 for w, and
1 for x
- just ad 'em up - for base perms,
and for specials,
4 for SUID,
2 for SGID,
1 for sticky
- again just add 'em up (and remember specials are at the MSb end).
And easy way to remember the ordering on the special bits - they're
again in ugo ordering as they effectively apply and have
corresponding effect.
-
read permission - the ability to read the contents
of the file. Note that a directory is a type of file.
Directories logically (and historically) contain only two things -
names of files within them (directly - e.g. the name of file
within), and the corresponding inode number of each.
So, if one can read the directory, one can determine the names of
the files in the directory, and their inode numbers.
-
write permission - ability to write to the file -
essentially alter the data of that file itself. Again, note that
directory is a type of file, and recall from above it contains
names of files and their inodes.
With write permission on a directory, one can:
add items to a directory, and also
(possibly notwithstanding sticky bit):
remove items from a directory and
rename items within a directory.
-
"execute" permissions. Ostensibly that
allows one
to "execute" the file. More precisely
if the file is a binary executable, one can execute it.
Note however, that if x
permission is lacking, but r permission is present, one can
generally work around lack of x permission (e.g. by copying the
file, changing permissions on copy, and executing copy, or using
something that will read/load and execute the file / file's
data).
x permission on directory is interpreted more as access,
notably ability to cd(chdir) into the
directory and access contents within (notwithstanding permissions
on the files within), e.g. [l]stat the files within, and do
whatever the permissions of the files within allow
-
"special"/extended permissions - the first three highest
bits in MSb to LSb order, are respectively,
Set User ID (SUID),
Set Group Id (SGID), and
sticky bit.
-
If SUID is set on binary executable, when the file is executed,
Effective UID (EUID) is set to UID that owns the binary.
-
Likewise if SGID is set on binary executable, when the file is
executed, Effective GID (EGID) is set to the GID that has group
ownership of the binary.
If SGID is set on directory, files created in directory will have
group ownership matching directory - and if it's a directory
created, its SGID bit will also be set (this is customary/historic
BSD behavior), if SGID is not set, file created in directory will
have group ownership of the EGID of the process (this is
customary/historic System V behavior).
-
Sticky bit. Historically for binary executable
files, that
would indicate to the kernel to (try to) retain the executable in
RAM after execution (e.g. to improve performance by avoiding
needing to again read it in from disk to RAM upon subsequent
execution). That use of t is mostly historic, or may only be taken
as a (slight) hint/suggestion to the kernel - or in many/most cases
is completely ignored in that regard.
Sticky bit on
directory - if set, that disallows non-owner of files in directory
from renaming or removing such items unless they have owner or
group write permissions on the directory. E.g. this is most
commonly used on /tmp and /var/tmp - which is necessarily ugo
writable - without the t, any user could generally remove or rename
files owned by others within those directories -
sticky bit on
directory prevents such shenanigans (and the security issues that
would open up).
- Algorithm:
Permissions are checked at open(/opendir) - generally not
subsequently (see also further below).
Permissions on symbolic links don't matter, though their user/group
ownerships matter in some contexts.
If EUID is 0 ("root"), all permissions are allowed (note
however some applications may further check permissions and
possibly warn or ask, but that can generally be overridden, and
generally without need to change permissions).
If EUID is not 0, we proceed with:
The u permissions are checked - if EUID matches owner of file, u
permissions are applied, no further permissions (at least among
ugo) are considered, otherwise we proceed with:
The g permissions are checked - if EGID matches group owner of file,
g permissions are applied, no further permissions (at least among
ugo) are considered, otherwise
we check any supplemental group memberships in order, if we find
match to group owner of file, upon first match found
g permissions are applied, no further permissions (at least among
ugo) are considered, otherwise
we proceed with:
The o permissions are checked and applied.
-
more on algorithm - permissions are checked at open(/opendir), and
mostly not subsequently (though applications and such may do so).
So, e.g., in general, once a process has opened a file, it
continues to have whatever access/permissions it had when it
opened the file - and that continues until the process has closed
the file. There are, however, some exceptions. There do exist
system calls that can, e.g. invalidate a file handle (or directory
handle). They can be used to prevent any and all subsequent I/O
operations on an existing open handle. Typical usage would be tty
devices. E.g. between init process, and often/typically getty and
login processes or the like, when a user logs in and is given a tty
(e.g. interactive session), that tty is reassigned (chowned) to
that user. User can then, e.g. open that file, read from it, write
to it. Well, what happens when they logout and some other user
comes along and gets assigned to that same tty device? Can the
earlier user still read and write that tty device? Were it not for
these system calls, they could. The managing process(es) (e.g.
init/getty/login) take care of that - having assigned a tty device,
they'll track that, when the login session goes away, they'll do
system call(s) to invalidate any filehandles that are open on that
tty device, thus, e.g., preventing the logged out user from
continuing with access via any processes of theirs that still have
that tty device open.
-
display/usage e.g. ls and chmod. The ls command generally
displays the permissions information MSb to LSb for the
"ordinary" permissions, then overlays the
"special" permissions information atop that.
It shows a
leading character for type of file (e.g. - for ordinary file, d for
directory),
next three characters are respectively rwx if set, - if clear, for
u.
Then likewise next 3 for g, and last 3 for o.
If SUID/SGID is set,
corresponding u or g will, instead of x, show s, however if the
corresponding SUID/SGID is set but corresponding x clear, S will be
shown instead of s.
For sticky bit, the o x will be
replaced with t - unless that x is clear, in which case instead T
will be displayed.
With chmod, these can be set using octal (POSIX
deprecated that at one point, but went back on that), e.g.
chmod 2770
or
chmod ug=rwx,g+s,o=
will set rwx for u and g, clear them for o, and set the SGID bit.
E.g. that may be suitable where one
wants owners and members of the group to have full permissions on
the directory, but any others, no permissions, and also, regardless
of the EGID of PIDs creating items in the directory, they'll have
group ownership matching the directory (but one must at least be
owner or member of the group to have access to the directory - but
it needn't be the PID's EGID).