Errors in setting permissions are the often-frustrating cause of many common Linux problems, so learn the fundamentals of permissions and take the first step to understanding Linux security.
For most of the Paranoid Penguin's illustrious four years with Linux Journal, I've tended to write tools-focused columns. I've described how to secure Sendmail, how to add SSL encryption to things by using Stunnel and how to get any number of other powerful security software tools configured and running.
Over the next couple of columns, however, I am going to address one of the most basic and important, yet often-overlooked aspects of Linux security; filesystem permissions. If used wisely, it will be harder for users and intruders to abuse their system privileges. If you set them carelessly, however, minor vulnerabilities can lead to major system compromises.
These articles should be especially useful to Linux newcomers who wonder what all the drwxr-xr-x gobbledygook in file listings means. But, even if you're an intermediate user—perhaps the kind who doesn't yet understand the precise ramifications of setuid and setgid—these articles, especially Part II, may have something for you too.
Did you know that in UNIX and UNIX-like systems, basically everything is represented by files? Documents, pictures and even executable programs are easy to conceptualize as files on your hard disk. Although we think of a directory as a container of files, a directory actually is a file containing, you guessed it, a list of other files.
Similarly, the CD-ROM drive attached to your system seems tangible enough, but to your Linux kernel, it too is a file—the special device file /dev/cdrom. To send data from it or to write it to the CD-ROM drive, the kernel actually reads to and writes from this special file. Actually, on most systems, /dev/cdrom is a symbolic link to /dev/hdb or some other special file. And wouldn't you know it, a symbolic link is in turn nothing more than a file containing the location of another file.
Other special files, such as named pipes, act as input/output (I/O) conduits, allowing one process or program to pass data to another.
My point here is not to describe each and every type of file that exists in Linux or UNIX. It's to illustrate how nearly everything is represented by a file. Once you understand this, it's much easier to understand why filesystem security is such a big deal and how it works.
Actually, two things on a Linux system aren't represented by files, user accounts and group accounts, which we call users and groups for short. Various files contain information about a system's users and groups, but none of those files actually represents them. A user account represents someone or something capable of using files. This is to say, both human beings and system processes can use user accounts. For example, a user account named webmaster typically represents a human being who maintains Web sites. But the standard Linux user account lp is used by the line printer dæmon (lpd); the lpd program runs as the user lp. I explain later what it means for a program to run as one user vs. another.
A group account simply is a list of user accounts. Each user account is defined with a main group membership but may in fact belong to as many groups as needed. For example, the user maestro may have a main group membership in conductors and also belong to pianists.
A user's main group membership is specified in the user account's entry in /etc/password. You can add that user to additional groups by editing /etc/group and adding the user name to the end of the entry for each group to which the user should belong. Alternatively, you could use the usermod command; see the usermod(8) man page for more information.
Listing 1 shows maestro's entry in the file /etc/password, and Listing 2 shows part of the corresponding /etc/group file.
In Listing 1, we see that the first field contains the name of the user account, maestro. The second field (x) is a placeholder for maestro's password, which actually is stored in /etc/shadow. The third field shows maestro's numeric user ID, or uid; in this case it's 200. The fourth field shows the numeric group ID, or gid—in this case it's 100—of maestro's main group membership. The remaining fields specify a comment, maestro's home directory and maestro's default login shell.
In Listing 2, from /etc/group, each line simply contains a group name, a group password (usually unused—x is a placeholder), numeric group ID (gid) and a comma-delimited list of users with secondary memberships in the group. Thus, we see that the group conductors has a gid of 100, which corresponds to the gid specified as maestro's main group in Listing 1. We also see that the group pianists includes the user maestro, plus another named volodyia, as a secondary member.
The simplest way to modify /etc/password and /etc/group in order to create, modify and delete user accounts is by using the commands useradd, usermod and userdel, respectively. I'd rather concentrate here on concepts than command syntax, so suffice it to say that all three of these commands can be used to set and modify group memberships and all three commands are well documented in their respective man pages. To see a quick usage summary, you also can type the command followed by --help, for example, useradd --help.
Each file has two owners, a user and a group, each with its own set of permissions that specify what the user or group may do with the file—read it, write to it and execute it. A third set of permissions pertains to what others, user accounts that don't own the file or belong to the group that owns it, can do with the file. Listing 3 shows a long file listing for the file /home/maestro/baton_dealers.txt.
Permissions are listed in the order of user permissions, group permissions and other permissions. For the file shown in Listing 3, its user owner (maestro) can read and write the file (rw-); its group owner (conductors) also can read and write the file (rw-), but other users can only read the file. Permissions are a little more complicated, however. Users classified as other, in terms of permissions on a particular file, can delete any file in a directory to which they have write permissions. In other words, users with read-only permission on a file cannot edit the file but can delete it if they have write permission on the file's directory.
There's a third permission besides read and write: execute, which is denoted by x when set. If maestro writes a shell script named punish_bassoonists.sh and if he sets its permissions to -rwxrw-r--, he then can execute this script by entering the name of the script at the command line. If, however, he forgets to set the execute permission, he is not able to run the script, even though he owns it.
Permissions usually are set with the chmod command, short for change mode. Continuing with our example, suppose maestro has second thoughts about allowing other members of the conductors group to read his list of baton dealers. He could remove the group read/write permissions using the commands shown in Listing 4.
In Listing 4's sample chmod command (chmod go-rw), go tells chmod to change the group permissions and other permissions; -rw says to remove read and write permissions for those two categories of permissions, group and other. Thus, a chmod command has three parts: a permission category, some combination of u, g and o or a for all; an operator, - to remove, + to add; and a list of permissions to add or remove, usually r, w or x.
We now know how to change basic permissions on regular files, but what about directories? Directory permissions work slightly differently from permissions on regular files. Read and write are similar; for directories these permissions translate to list the directory's contents and create or delete files within the directory, respectively.
Execute is a little less intuitive on directories, however. Here, execute translates to use anything within or change working directory to this directory. That is, if a user or group has execute permissions on a given directory, the user or group can list that directory's contents, read that directory's files (assuming those individual files' own permissions include this) and change the working directory to that directory with the command cd. If a user or group does not have execute permission on a given directory, the user or group is unable to list or read anything in it, regardless of the permissions set on the things inside. If you lack execute permission on a directory but do have read permission and you try to list its contents with ls, you receive an error message that, in fact, lists the directory's contents. But this doesn't work if you have neither read nor execute permissions on the directory.
Suppose our example system has a user named biff who belongs to the group drummers. Also suppose that his home directory contains a directory called extreme_casseroles that he wishes to share with his fellow percussionists. Listing 5 shows how biff might set that directory's permissions.
Per Listing 5, only biff has the ability to create, change or delete files inside extreme_casseroles. Other members of the group drummers can list its contents and cd to it. Everyone else on the system, however, is blocked from listing, reading, cd-ing or doing anything else with the directory.