Unix Permissions - Part 1: Anatomy of Permissions
Introduction
permission denied
: an error message that every command line user has faced before. Often times, users solve this by running sudo [previous command]
(sometimes without considering consequences!). The error arises due to Traditional Unix Permissions System: The security mechanism that POSIX operating systems use by default, to protect the system from malicious actors, compromised processes, or even user mistakes and errors. Whether you aim to secure your system, or improve your productivity when working around an existing permission on your Linux or MacOS computer, learning how to use Unix permissions is a crucial part of system administration and day-to-day command line usage.
Summary
In this article, we will talk about the traditional Unix permission system. We will talk about what it is exactly and how it works under the hood. We will break down the system into its individual peaces, and talk about each one individually, and how they all tie in together, to gain a full understanding of how it all works.
This is the first part of a series; the next parts will explore part of the suite of command-line tools offered to us to use and work around this security system, and look at an example of using the Unix permissions to architect our system's security model. Please check them out as well!
Pre-requisites
Basic familiarity with a Unix-like system (Linux, macOS, or BSD) and the command line is encouraged, but not absolutely necessary.
Anatomy and Model of Unix Permissions
There are 5 main entities in traditional Unix Permissions:
- User: The elementary unit. Has permissions associated with it
- Group: a group of users
- File: the entity we are imposing protections on
- Process: Gets assigned a user to gain its permissions
- File Permissions: denotes which users (and groups) have which accesses to a certain file
To understand how each of those work together, let us explore them in detail one-by-one.
User
When you first hear the word "user", you might imagine an actual person that uses the computer. This is how most people use them in Microsoft Windows, and indeed, Unix systems used them the same way initially. Most early computers were used by multiple people, and Traditional Unix permissions system was deliberately developed to secure users from each other. Our modern threats of malware or spyware from the internet were non-existent in that time.
However, times have changed. Nowadays, most computers are not multi-user, and in cases which they are, other users using the same machine are the least of your security worries. Threats coming from the internet (malware, hackers, etc) or vulnerabilities from the many applications installed on your system are far more important.
But the user model can still satisfy modern needs if we think of users differently. Instead of associating a user with a person, we conceptualize it as a unit that has a collection of permissions, and can be assigned to a process (including a login shell session) so that said process adopts that user's permissions. Upon attempting to access a file, the operating system will check the permissions associated with the file, and confirm that the user has the necessary permissions to perform the operation.
Group
A group is, as you'd expect, a group of users. It is a many-to-many relationship; a user can belong to multiple groups, and a group can have multiple users.
Like users, groups also have permissions associated with them. If a user is part of a group, they are granted the group's permissions.
As we will see later, groups are a key component in allowing many-to-many relationships between users and their permissions to access files. It is only with groups that we are able to grant accesses to a file to more than one user.
Permissions
Permissions are the core component of Unix permissions. Each file has three types of permissions:
- Read: Ability to open the file and read its content (or copy it)
- Write: Ability to modify the file's content, completely overwrite it, or delete it
- Execute: Ability to run as a process (relevant for programs or scripts)
These permissions are defined separately for each "scope". A scope is a certain grouping of users. Each file has 3 scopes associated with it:
- The user that owns the file, or the owner.
- The file's group, or group owner.
- other: All other users not included in the other scopes
For example, for a specific file, we can say:
- The (user) owner has read and write access to the file.
- The users belonging to the file's group have read access to the file. They can check out its content but cannot modify anything.
- All other users have no permissions to this file. They cannot see its content or modify it
This would be an example of a list of permissions associated with a file.
Files
Files are the element that Unix permissions system aims to protect. As we saw earlier, each file has a set of permissions associated, defining which users can do what. This is dictated by the file's owner and group, which are also defined separately for each file.
Upon creating a new file, it is usually assigned the owner and group based on the process or shell session that created it, but they can be changed. Setting the right owner and group is an important step in devising a security model to protect a certain file or your system as a whole. We will discuss this more deeply in later sections.
How it Really Works
Let us now describe how the operating system manages access in traditional Unix permissions. We will take a scenario where a certain user attempts to access a certain file. How exactly can we predict if the access will be granted?
Initial Setup
- We start with a regular Linux system
- The system already has a set of files on its filesystem, and a set of users and groups defined
- Each file on the syetm has a user owner and a group owner
- Each file will have defined a list of permissions, denoting:
- What accesses (read, write, or execute) the user owner has
- What accesses the group owner has
- What accesses all other users have
Putting Unix Permissions to Test!
Let's see what it would look like if Unix permissions on the system we setup above are put to test.
- Suppose a user (or process) tries to access a file, the following happens
- The system determies type of access requested. Is it read, write, or execute?
- Next, the system determines which scope the user falls into
- Is the user the user owner of the file? Then the scope is "user"
- Does the user belong to the group owner of the file? THen the scope is "group"
- If none of the above, the scope is "other"
- The system fetches the permissions associated with the scope determined in the previous step
- The system checks whether the requested access in the list of permissions for that scope
- If the system verifies that the requested access is in the permissions, then access is granted. Otherwise, access is rejected.
NOTE: This is a conceptual model to help us understand how it works, and is not meant to represent the exact implementation behind the scenes.
Conclusion
We now have a conceptual model of how Unix permissions work, which will be very handy when troubleshooting issues or securing a certain system or file. Whenever you come across a complex issue, trying to imagine the possible steps the system took to arrive at the error message it gave you can be the key to finding the solution, or they key to finding the vulnerability in your security model.
In part 2 of this series, we will dive into command line tools that help us work with permissions, such as setting or modifying permissions, or setting or modifying file owners or groups. Please check it out and give me feedback if you have it!