Because Linux is a multi-user system - whether operated stand-alone or as a network server, it becomes important to keep users' files separate and to enforce access controls to minimise either accidental or malicious damage to files. While this is obviously most useful in the corporate/academic world for which UNIX was designed, it is even useful in a home setting, as any parent of several squabbling children can attest!
Each user on a Linux system has a user name and password, which he uses to log in. However, once logged in, the system actually tracks that user by a numeric user ID, as this is faster, as well as a group ID. The user ID number is usually 500 or greater, with lower numbers being reserved for system use, and uniquely identifies the user. The group ID may identify a group with many members, or the group may contain just one member, depending on the administration philosophy of the Linux distribution you are using.
A Linux system also has a number of system accounts, which are not intended for use by human users. Usually these accounts are used by daemon processes, to allow them to safely access devices and files normally inaccessible to other users. For example, you can see your ID numbers, by using the id command:
[les@freya2 les]$ id
uid=500(les) gid=500(les) groups=500(les),507(c34k)
In the same way as a user has a user and group ID, so a file has an ID number for the user who owns it, plus an ID number for the group that owns it.
Whether or not you are able to read, write or otherwise manipulate a file depends upon firstly, whether you are the owner of a file, a member of the group that owns a file, or just an innocent bystander. Secondly, your access depends upon the permissions that apply to you by virtue of your relationship to the file.
Filesystem essentials: directories and inodes
In order to understand these concepts, we need to first of all examine how files are stored in most Linux (and UNIX) filesystems. The file's data is stored in blocks - usually 1 KByte in size - on the disk surface. The filesystem keeps track of the blocks that are used by recording the block numbers in data structures called inodes. A file will always have at least one inode, but it may have more, especially since the first inode only has space to keep track of 12 blocks. So, if a file is greater than 12 KBytes in size, it must have more than one inode. But we don't care about that - the first inode is the most important to us right now.
The remaining space in that first inode is where the filesystem records most of the important information about a file. In particular, the inode contains the following pieces of data:
- The uid of the user who 'owns' the file
- The gid of the group that 'owns' the file
- The file permissions, also known as the file mode.
- atime: time of last access: show with the ls -lu command
- ctime: time of last modification of file status information in its inode: show with the ls -lc command
- mtime: time of last modification of file contents: show with the ls -l command
You can see most of this information with the ls command, using the -l option to get a 'long format' listing, and perhaps the -c and -u options to see the ctime or atime instead of the mtime. If you really want to know the full details of how an inode works, go look at the file /usr/include/linux/fs.h on your system for the definition of an inode.
In order to allow for logical organisation of files, Linux filesystems support directories. A directory is just a list of filenames, together with their inode numbers, although the operating system protects you from damaging the system by accidentally editing or deleting directories. So, to access a file, the system finds its directory entry, reads the inode number, and then reads the inode. Whether you then get access to the file depends upon the permissions in the inode.
An interesting aside: Since a directory entry simply consists of a name and an inode number, it is certainly possible to have two or more directory entries - in the same or different directories - with the same inode number. These are called hard links, and they are somewhat similar to, but more reliable than - Windows shortcuts. Notice that since the permissions are stored in the inode - and there is still just one inode - all links will have the same permissions.
Now, if you execute an ls -l command, you will see that the output begins with the following columns of characters:
|Column position||File type||Meaning|
|First column||-||Ordinary file|
|Three letter file owner permissions||r||Read|
|s||Set user ID|
|Three letter group permissions||r||Read|
|s||Set group ID|
|Three letter other (world) permissions||r||Read|
The first column shows the file type. A dash simply indicates an ordinary file, while a d indicates a directory. A l indicates that this is a symbolic link, which contains the pathname of another file and allows you to manipulate that file indirectly - for example, try to edit that symbolic link (e.g. vi other-file) and you will actually be editing a file somewhere else. Symbolic links basically behave very much like hard links. If you look in the /dev directory, you will see that many of the files are of types b and c - these are block devices, which write a sector or block of data at a time (disk drives, mostly), and character devices, which write a character at a time (serial ports, modems, etc.)
The next set of nine characters specify the access permissions or mode for the file. Now, obviously you will want to distinguish between the permissions you should have, as owner of a file, from the permissions which apply to the people you work with and perhaps other people you don't. To support this, UNIX and Linux filesystems support three sets of permissions:
- user - permissions that apply to the user who owns the file
- group - permissions that apply to the group who share ownership of the file
- other or world - permissions for everybody else
When you create a file, the inode is set up with the owner id set to your uid, and the group owner ID set to your primary group ID. So immediately, the system 'knows' the file is owned by you and your group.
Permissions on files
Permissions on files are fairly straightforward.
The r permission allows you to read the file, i.e. view its contents
The w permission allows you to write to a file, i.e. change its contents, delete it and rename it.
If the file is a program - and it should be - you can execute it. You would turn on the x permission on scripts that you want to make executable, for example.
The sticky bit
The sticky bit is something of a holdover from the days of very small-memory systems. Originally it was intended to be set on executable program files to get the system to keep the program in memory after it had finished, ready to be run again without the overhead of reloading it. On more modern systems like Linux, it causes the program code to be kept in the swap partition for faster reloading.
The setuid bit
Normally, when a program runs, its effective uid is the same as the id of the user who invoked it. However, when the SUID bit is turned on, the effective uid of a running program becomes the id of the user who owns its file. Very often, this is the root account, but sometimes it is some other system account. This mechanism can be used to let users run programs which are able to access files or devices that the user him/herself would not normally be able to access. It is commonly used by subsystems like the print spooler subsystem (user lp), and programs which access serial ports and modems, like uucp. Another example is the passwd command:
[les@freya2 sbin]$ ls -l /usr/bin/passwd
-r-s--x--x 1 root root 15104 Mar 14 2002 /usr/bin/passwd
You can see that this program is owned by root, and has the execute permission turned on for all users, plus the read permission for root, who may need to copy the file (unlike other users who can only execute it). It also has the setuid bit turned on, so that when an ordinary user runs it, it changes its effective user id to 0, the root id, so that it is able to update the /etc/shadow file, where passwords are actually stored, and which is inaccessible to ordinary users:
[les@freya2 sbin]$ ls -l /etc/shadow
-r-------- 1 root root 1104 Apr 16 16:27 /etc/shadow
Programs with the setuid bit are a security risk albeit a necessary one. You can find all the setuid programs on your system with the command:
[root@freya2 root]# find / -perm +4000 -ls
find: /proc/1543/fd/4: No such file or directory
128818 40 -rwsr-xr-x 1 root root 37528 Jan 18 2002 /usr/bin/at
129778 16 -rwsr-xr-x 1 root root 14588 Jul 24 2001 /usr/bin/rcp
129000 12 -rwsr-xr-x 1 root root 10940 Jul 24 2001 /usr/bin/rlogin
129001 8 -rwsr-xr-x 1 root root 7932 Jul 24 2001 /usr/bin/rsh
128924 36 -rwsr-xr-x 1 root root 34296 Mar 28 2002 /usr/bin/chage
The setgid bit
This bit is similar to the setuid bit, except that it changes the effective uid of the program to that of the group which owns the file.
Changing Permissions with the chmod Command
So, how do you change permissions on your file to protect them? That's where the chmod (change mode) command comes in. The syntax of chmod is
chmod [option ...] [mode] file ...
The mode can be expressed numerically, as an octal number representing the permissions to be set, or symbolically. The format of a symbolic mode is:
and multiple modes can be concatenated, separated by commas. u represents the user's permissions, g represents the user's primary group's permissions and o represents the permissions of all other users, while a represents all three sets of permissions. The use of a + symbol adds the specified permissions to those the file already has, while a - sign removes those permissions. Use of a = sign sets the permissions to just those specified.
See Table 2 for definitions of modes, but briefly: r = read, w = write, x = execute, X = execute only if the file is directory or execute permission is already set for some user, s = setuid, t = sticky bit, u = the user's permissions, g = the file's group's permissions, o = the permissions for all other users.
Table 2 - chmod Options
|-c, --changes||Like verbose, but report only changes|
|-f, --silent, --quiet||Suppress most error messages|
|-v, --verbose||Print a message for every file processed|
|--reference=ref-file||Copy the permissions from ref-file|
|-R, --recursive||Change files and directories recursively|
|--help||Print a usage message and exit|
|--version||Print a version number and exit|
So, if you have a file called accounts.doc, which is currently readable by everyone, and you want to turn that off so that only members of your group can view it:
[les@freya2 les]$ ls -l accounts.doc
-rw-rw-r-- 1 les les 19968 Mar 2 21:33 accounts.doc
[les@freya2 les]$ chmod o-r accounts.doc
[les@freya2 les]$ ls -l accounts.doc
-rw-rw---- 1 les les 19968 Mar 2 21:33 accounts.doc
This has turned off the r permission for others.
Permissions on directories
But what do these permissions mean for directories, which you can't normally read, write or execute? The permissions for directories have some subtle twists, and many users have a less-than-perfect understanding of them.
The r permission allows search access to the contents of the directory, i.e. the names of the files within it. This allows you, for example, to run the ls command - without any arguments. It does not imply that you have access to the files in the directory - you can just read their names. Remember, a directory is simply a file: with the r permission, you are able to read the contents of that file, which is basically the file names.
The w permission allows you to update the directory contents, i.e. to create, rename and delete files. Notice that to delete a file, you really should have w permission on both the file itself and the directory it is in; however, technically, only w permission on the directory is required - if you do not have w permission on the file, the system will ask you if you want to override the protection on the file.
The x permission allows access to the directory. This allows you to cd to the directory and access any file within it by name, but not to search the directory. To search the directory, you need to be able to read its contents, which imples the r permission.
A useful way to think of the effect of the r and x permissions on directories is to remember that a directory is just a list of filenames and inode numbers. The r permission lets you read this. The x permission lets you follow the the inode numbers and read the inodes of the files in the directory itself, which is required to access the files or to display their attributes, as done by an ls -l command. This explains why running an ls command requires only r permission on the directory, but ls -l requires both r and x (see Table 3 below).
The sticky bit on a directory indicates that, despite the write permission, users cannot delete a file unless they own either the file or the directory. This allows programs to - for example - append to or update files, but not delete them.
With the setuid bit set on a directory, files created in a directory will have the same ownership as the directory itself, regardless of who creates them. This is particularly useful in directories which are shared by multiple users who are all members of a group:
[les@freya2 les]$ ls -ld projectalpha
drwxrwsr-x 2 les staff 4096 May 21 07:24 projectalpha
[les@freya2 les]$ cd projectalpha
[les@freya2 projectalpha]$ touch newfile; ls -l newfile
-rw-rw-r-- 1 les staff 0 May 21 07:24 newfile
You can see here that the projectalpha directory has the setgid permission turned on and is owned by the staff group, so that when I cd into it and create a new file (with the touch command), the file is also owned by the staff group.
With the setgid bit set on a directory, files created in a directory will belong to the same group as the directory does, regardless of the effective gid of the creator
What Do I Need?
Table 3 summarises the permissions required in order to perform various actions on a file or directory:
Table 3 - Required directory permissions
|In order to:||You need these permissions|
|on the source directory:||on the file:||on the destination directory:|
|List files in a directory (ls command)||r--|
|Long format list files in a directory (ls -l)||r-x|
|cd to a directory||--x|
|mkdir or rmdir||-wx|
|Create a file||-wx|
|Read a file||--x||r--|
|Write to a file||--x||-w-|
|Edit a file (read it in, write it back)||--x||rw-|
|Copy a file (cp)||--x||r--||-wx|
|Copy a tree (cp -r)||r-x||r--||-wx|
|Move a file (mv)||-wx||---||-wx|
|Delete a file (rm)||-wx||---|
Note especially the last two rows - that to move or delete a file, you don't need to have any permissions on it at all, only write and execute permissions on the directory that contains the file.
What happens when you create a file?
How are the permissions originally set? This is controlled by a variable called the umask, which specifies which permissions should be turned off. You can see your umask with the command " umask -S " but in general, for a newly created file, the permissions will be set to rw-rw-rw- and then the umask value of 0002 is applied, to turn off the w permission for others, resulting in rw-rw-r--. For directories, the permissions will be rwxrwxrwx, but with the umask value subtracted, it becomes rwxrwxr-x.
You can change your umask for yourself as you work, with the umask command. As you can see, by default, your files will be readable by all users on the system. If you want to change this, you should change the umask:
[les@freya2 les]$ umask -S
[les@freya2 les]$ umask o=x
[les@freya2 les]$ umask -S
The entry for each user in /etc/passwd specifies a group id for that user, which is his/her primary group, also known as a login group. By default, any files created by that user will have group ownership set to the primary group id. However, a user can also be a member of many other groups, which are referred to as secondary groups.
This is accomplished by listing the users who are members of a group in that group's entry in the /etc/group file. Here is an extract:
You can see that the group c34k has four members. Users can be added to groups at the time that the users are added to the system (with the useradd command's -G option, or later with the usermod command - again, using the -G option.. You can see the groups you are in with the groups command:
[les@freya2 les]$ groups
In the Linux world, there are basically two different approaches to how users are allocated to groups
Common group philosophy
Most Linux distributions add new users to a group called "users", which is also the primary group for human users. This means that, by default, users' files are shared with all other users and access controlled by the group permissions. Typically, the umask is set to 0022 or 0024, so that members of your primary group can read but not write files you create, while world cannot write and perhaps not read them.
Red Hat's User Private Group Philosophy
On Red Hat Linux, when a new user is created, a group of the same name is also created, and that group is the user's primary group. This means that by default, users only have access to each others' files by virtue of the " other" or "world" permissions. However, if you want to allow co-workers access to your files, all you have to do is add those users to your group. With the default umask value of 0002, files that you create will be writeable by other members of your group.
In order for this to work correctly, the user has to additionally be made administrator for their own group with the gpasswd command. The syntax is:
gpasswd -A user group ...
So, for example, to add a user called Bob and make him administrator of his own group:
gpasswd -A bob bob
Now, Bob can add his secretary, Sue, to his group so that she can access his files:
gpasswd -a sue bob
One other little convenience of the Red Hat scheme is that groups will often need a directory where they can share files, and creating a user with the desired group name has the effect of creating the group and also creating a home directory for that group.
You now have all the tools required to secure the files you want to keep private, while sharing files between different groups of users. In a home setting, you could use Red Hat with its private group scheme to let each family member keep their private files truly private, while creating a secondary group for kids, with a shared directory that lets the kids share their files and the setgid bit turned on so that files created their are owned by the group 'kids'. Another similarly-configured directory can be used to share all family photographs, shared documents, etc. And with these directories shared by Samba, all family members will be able to get the appropriate access from their Windows desktop PC's, if that's what they use.
Similarly, in an office setting, groups can be set up on a departmental basis to allow shared access to files, with other departments denied access.
The Linux access control mechanism is simple, but effective, and an understanding of it can keep your information secure, while allowing easy sharing where necessary.