Permissions
Overview
Teaching: 25 min
Exercises: 15 minQuestions
Understanding file/directory permissions
Objectives
What are file/directory permissions?
How to view permissions?
How to change permissions?
File/directory permissions in Windows
Unix controls who can read, modify, and execute files using permissions. We’ll also discuss Windows permissions later, as the concepts are similar but implementation differs.
Let’s start with a normal user called Nelle.
She has a unique user name (e.g., nelle
), and a user ID, (a unique number, like 1404
).
Why Integer IDs?
Why integers for IDs? Again, the answer goes back to the early 1970s. Character strings like
alan.turing
are of varying length, and comparing one to another takes many instructions. Integers, on the other hand, use a fairly small amount of storage (typically four characters), and can be compared with a single instruction. To make operations fast and simple, programmers often keep track of things internally using integers, then use a lookup table of some kind to translate those integers into user-friendly text for presentation. Of course, programmers being programmers, they will often skip the user-friendly string part and just use the integers, in the same way that someone working in a lab might talk about Experiment 28 instead of “the chronotypical alpha-response trials on anacondas”.
Users can belong to any number of groups,
each of which has a unique group name
and numeric group ID.
The list of who’s in what group is usually stored in the file /etc/group
. To see all the groups on a Unix system, you can run:
cat /etc/group
Now let’s look at files and directories. Every file and directory on a Unix computer belongs to one owner and one group. Along with each file’s content, the operating system stores the numeric IDs of the user and group that own it.
The user-and-group model means that for each file every user on the system falls into one of three categories:
- Owner - the owner of the file (User -
u
) - Group - someone in the file’s group (
g
) - Others - everyone else. (
o
)
For each of these three categories, the computer keeps track of whether people in that category can read the file, write to the file, or execute the file (i.e., run it if it is a program).
For example, if a file had the following set of permissions:
user | group | all | |
---|---|---|---|
read (r) | yes | yes | no |
write (w) | yes | no | no |
execute (x) | no | no | no |
it would mean that:
- the file’s owner can read and write it, but not run it;
- other people in the file’s group can read it, but not modify it or run it; and
- everybody else can do nothing with it at all.
Let’s look at this model in action. Now let’s download some sample data for test and for checking the permission. So, please run:
# to download the data
wget https://noc-oi.github.io/shell-extras/data/labs.zip
# to unzip the data
unzip -l labs.zip
If we cd
into the labs
directory and run ls -F
,
it puts a *
at the end of setup
’s name.
This is its way of telling us that setup
is executable,
i.e.,
that it’s (probably) something the computer can run.
cd labs
ls -F
final.grd safety.txt setup* waiver.txt
Necessary But Not Sufficient
The fact that something is marked as executable doesn’t actually mean it contains a program of some kind. We could easily mark this HTML file as executable using the commands that are introduced below. Depending on the operating system we’re using, trying to “run” it will either fail (because it doesn’t contain instructions the computer recognizes) or cause the operating system to open the file with whatever application usually handles it (such as a web browser).
Now let’s run the command ls -l
:
ls -l
-rwxrwxrwx 1 nelle bio 4215 2010-07-23 20:04 final.grd
-rw-rw-r-- 1 nelle bio 1158 2010-07-11 08:22 safety.txt
-rwxr-xr-x 1 nelle bio 31988 2010-07-23 20:04 setup
-rw-rw-r-- 1 nelle bio 2312 2010-07-11 08:23 waiver.txt
The -l
flag tells ls
to give us a long-form listing.
It’s a lot of information, so let’s go through the columns in turn.
On the right side, we have the files’ names. Next to them, moving left, are the times and dates they were last modified. Backup systems and other tools use this information in a variety of ways, but you can use it to tell when you (or anyone else with permission) last changed a file.
Next to the modification time is the file’s size in bytes
and the names of the user and group that owns it
(in this case, nelle
and bio
respectively).
We’ll skip over the second column for now
(the one showing 1
for each file)
because it’s the first column that we care about most.
This shows the file’s permissions, i.e., who can read, write, or execute it.
Let’s have a closer look at one of those permission strings:
-rwxr-xr-x
.
The first character tells us what type of thing this is:
‘-‘ means it’s a regular file,
while ‘d’ means it’s a directory,
and other characters mean more esoteric things.
The next three characters tell us what permissions the file’s owner has.
Here, the owner can read, write, and execute the file: rwx
.
The middle triplet shows us the group’s permissions.
If the permission is turned off, we see a dash, so r-x
means “read and execute, but not write”.
The final triplet shows us what everyone who isn’t the file’s owner, or in the file’s group, can do.
In this case, it’s ‘r-x’ again, so everyone on the system can look at the file’s contents and run it.
To change permissions, we use the chmod
command
(whose name stands for “change mode”).
Here’s a long-form listing showing the permissions on the final grades
in the course Nelle is teaching:
ls -l final.grd
-rwxrwxrwx 1 nelle bio 4215 2010-08-29 22:30 final.grd
Whoops: everyone in the world can read it—and what’s worse, modify it! (They could also try to run the grades file as a program, which would almost certainly not work.)
The command to change the owner’s permissions to rw-
is:
chmod u=rw final.grd
The ‘u’ signals that we’re changing the privileges
of the user (i.e., the file’s owner),
and rw
is the new set of permissions.
A quick ls -l
shows us that it worked,
because the owner’s permissions are now set to read and write:
ls -l final.grd
-rw-rwxrwx 1 nelle bio 4215 2010-08-30 08:19 final.grd
Let’s run chmod
again to give the group read-only permission:
chmod g=r final.grd
ls -l final.grd
-rw-r--rw- 1 nelle bio 4215 2010-08-30 08:19 final.grd
And finally, let’s give “others” (everyone on the system who isn’t the file’s owner or in its group) no permissions at all:
chmod o= final.grd
ls -l final.grd
-rw-r----- 1 nelle bio 4215 2010-08-30 08:20 final.grd
Here, the ‘o’ signals that we’re changing permissions for “others”, and since there’s nothing on the right of the “=”, “others”’s new permissions are empty.
Alternatively, you can also use numeric notation:
chmod 640 final.grd # Equivalent to rw-r-----
This sets:
- Owner: read (
r
) and write (w
). - Group: read (
r
) only. - Others: No permissions.
This is the meaning of the numbers:
Number | Meaning |
---|---|
7 | read, write, and execute |
6 | read and write |
5 | read and execute |
4 | read only |
3 | write and execute |
2 | write only |
1 | execute only |
0 | none |
We can search by permissions, too.
Here, for example, we can use -type f -perm -u=x
to find files
that the user can execute:
find . -type f -perm -u=x
./setup
Before we go any further,
let’s run ls -a -l
to get a long-form listing that includes directory entries that are normally hidden:
ls -a -l
drwxr-xr-x 1 nelle bio 0 2010-08-14 09:55 .
drwxr-xr-x 1 nelle bio 8192 2010-08-27 23:11 ..
-rw-r----- 1 nelle bio 1158 2010-07-11 08:22 final.grd
-rw-rw-r-- 1 nelle bio 1158 2010-07-11 08:22 safety.txt
-rwxr-xr-x 1 nelle bio 31988 2010-07-23 20:04 setup
-rw-rw-r-- 1 nelle bio 2312 2010-07-11 08:23 waiver.txt
The permissions for .
and ..
(this directory and its parent) start with a ‘d’.
But look at the rest of their permissions:
the ‘x’ means that “execute” is turned on.
What does that mean?
A directory isn’t a program—how can we “run” it?
In fact, ‘x’ means something different for directories.
It gives someone the right to traverse the directory, but not to look at its contents.
The distinction is subtle, so let’s have a look at an example.
Nelle’s home directory has three subdirectories called taiti
, vanuatu
, and tonga
:
- 📁 nelle
- 📁 taiti r-x
- 📄 notes
- 📁 vanuatu r--
- 📄 notes
- 📁 tonga --x
- 📄 notes
- 📁 taiti r-x
Each of these has a subdirectory in turn called notes
,
and those sub-subdirectories contain various files.
If a user’s permissions on taiti
are ‘r-x’,
then if she tries to see the contents of taiti
and taiti/notes
using ls
,
the computer lets her see both.
If her permissions on vanuatu
are just ‘r–’,
then she is allowed to read the contents of both vanuatu
and vanuatu/notes
.
But if her permissions on tonga
are only ‘–x’,
she cannot see what’s in the tonga
directory:
ls tonga
will tell her she doesn’t have permission to view its contents.
If she tries to look in tonga/notes
, though, the computer will let her do that.
She’s allowed to go through tonga
, but not to look at what’s there.
This trick gives people a way to make some of their directories visible to the world as a whole
without opening up everything else.
Shebang
Shebang is the #! syntax used in scripts to indicate an interpreter for execution under UNIX/Linux operating systems. For shell, we can use two different approaches,
#!/bin/bash
or,
#!/usr/bin/env bash
at the top of the script. The second approach is more portable and recommended.
For instance, check the file_info.sh
script in the code
directory.
First, after creating or downloading the script, we need to make it executable using chmod
command.
chmod u+x file_info.sh
The u+x
option is used to permit the “user to execute” the script.
Then we can run the script using the following command:
./file_info.sh example.txt
Shebang is necessary if we want to run the code without explicitly telling Unix what the interpreter is.
We still run the code without shebang, i.e., by telling the interpreter to run the code,
e.g., bash file_info.sh example.txt
. If we run the code directly but no shebang
is given, or the permission is not given, the code will not run (“Permission denied” error).
Add shebang and execute permission to Nelle’s scripts
Nelle has three scripts in the
north-pacific-gyre
directory calleddo-stats.sh
,goostats
andgoodiff
.Edit each of these using
nano
(or your text editor of choice) and add a#!/bin/bash
at the start. Give the owner and group execute permission on these scripts too.Previously we ran
do-stats.sh
by using the command:bash ./do-stats.sh <filename>
How can we run the script now?
Solution
nano do-stats.sh nano goostats nano goodiff chmod ug+x do-stats.sh chmod ug+x goo*
This means we can now start the scrit without the
bash
command. For example:./do-stats.sh <filename>
User Groups and Members
In Linux, users can belong to one or more groups, which help define access control for files and directories.
Each user has a primary group and can be part of additional groups. Groups are defined in the /etc/group
file.
To list a user’s group memberships, run:
groups username
For example, running groups nelle
might return:
nelle : nelle developers data-science
This means that Nelle belongs to the developers
and data-science
groups in addition to her own user group.
To view all groups on the system, use:
cat /etc/group
Adding a user to a group requires administrative privileges. The command to add a user to a group is:
sudo usermod -aG group_name username
For example, to add nelle
to the sysadmin
group:
sudo usermod -aG sysadmin nelle
To verify the change, log out and log back in, then rerun groups
.
To remove a user from a group:
sudo gpasswd -d username group_name
For example:
sudo gpasswd -d nelle developers
Access Control Lists (ACLs)
You can also use Access Control Lists (ACLs) to grant permissions to specific users or groups. It gives you finer-grained control and flexibility over file permissions. However, it is more complex to administer and understand on small systems (If you have a large computer system, nothing is easy to administer or understand.) For example, you could give the Mummy permission to append data to a file without giving him permission to read or delete it, and give Frankenstein permission to delete a file without being able to see what it contains.
Some modern variants of Unix support ACLs as well as the older read-write-execute permissions, but hardly anyone uses them.
Example of ACLs commands in UNIX
- Set ACL for a specific user:
setfacl -m u:alex:rwx filename
- Set ACL for a group:
setfacl -m g:groupname:r filename
- View ACLs on a file:
getfacl filename
- Remove an ACL entry:
setfacl -x u:username filename
What about Windows?
In Windows, permissions are defined by access control lists.
As in Unix, each file and directory has an owner and a group. However, Windows permissions are more complex than Unix permissions.
To view and change permissions in Windows:
- File Explorer: Right-click on a file, select
Properties
, and go to theSecurity
tab. - Command Line: Use the
icacls
command.
Challenge
If
ls -l myfile.php
returns the following details:-rwxr-xr-- 1 caro zoo 2312 2014-10-25 18:30 myfile.php
Which of the following statements is true?
- caro (the owner) can read, write, and execute myfile.php
- caro (the owner) cannot write to myfile.php
- members of caro (a group) can read, write, and execute myfile.php
- members of zoo (a group) cannot execute myfile.php
Key Points
Correct permissions are critical for the security of a system.
File permissions describe who and what can read, write, modify, and access a file.
Use
ls -l
to view the permissions for a specific file.Use
chmod
to change permissions on a file or directory.Use
chmod 777
carefully, as it grants all permissions to everyone.Access Control Lists (ACLs) provide finer-grained permission control.