Inheriting your rights
© 2010-2013 Dennis Leeuw dleeuw at made-it dot com
License: GPLv2 or later
Every operating system that supports one or more users needs a way to tell which user has rights on which file. This is not to make things more complicated, but to prevent one user from viewing another users data. So what we are talking about is permissions. You may have the permission to read or write some file, or you may not.
On Unix-like systems, like GNU/Linux, everything is a file, and since that is the case we need to be able to set rights on files, so we can decide who as access to which file.
Linux shows the rights on a file with the ls -l command. An example may look like this:
drwxrwxrwx 11 leeuw users 4096 May 7 12:09 doc -rw------- 1 leeuw users 240447 Jul 5 2000 mbox drwxr-xr-x 2 leeuw users 4096 Nov 30 15:15 naming drwx------ 2 leeuw users 4096 Apr 26 11:29 nsmail drwxr-xr-x 4 leeuw users 4096 Dec 14 16:43 pictures drwxr-xr-x 3 leeuw users 4096 Oct 18 2000 pilot -rw-r--r-- 1 leeuw users 172858 Apr 5 13:28 scripts.tar.gz drwxr-xr-x 2 leeuw users 4096 Jan 18 16:34 sysadmin drwxr-xr-x 4 leeuw users 4096 May 7 11:27 toolsHere we see 9 colomns of data in 9 rows. The rows are read from left to right. Let's start with the first row first column. The first colomn from our ls -l command shows the rights. The complete string drwxrwxrwx consists of four parts:
Type | Owner | Group | Other |
d | rwx | rwx | rwx |
The title might sound a bit strange. But directories are actually a list of hardlinks to the real content. So it is a list of inodes.
A special file within a file system is not the hardlink, but a symbolic link. You can create a symlink through the use of
ln -s file-original file-link
A symbolic link is a new inode that links to the inode of the file you link to. Meaning it takes up space on your system. While a hardlink is just another name pointing to the same inode. It is the second column in our example that represents the amount of (hard)links that is created to a certain inode. It is the so called reference count.
A file without links has always a reference count of 1 and a directory of 2. Next to the directory name pointing to the inode you also have the . within the directory pointing to the same inode. Creating a second directory in the first will add 1 reference to the first directory since in the second directory .. points to the inode of the first.
Next to the . and .. files you can store additional files in a directory which are hardlinks between the name and the inode. So directories are actually a collection of links.
Before we continue with the other fields and the rights we first look at the colomns 3 and 4 of our ls -l command. These say that the name under which the directory is created is leeuw, so the directory is owned by me. And the directory also belongs to the group users. When I logon to the system I type a username and a password. This username is in my case leeuw. Next to that the system apperently uses groups to which users can be long and the system administrator has put me in the group users.
Let's see what more I can find out about myself on the system.
With the command whoami it is possible to show who I am:
appel:~ > whoami leeuwand with id I can even see to which groups I belong:
appel:~ > id uid=514(leeuw) gid=100(users) groups=100(users),220(writers)This shows that next to the group users I also belong to the group writers.
With this last command there are a couple of new things that are shown. First there are the abbreviations uid (user identifier) and gid (group identifier), and behind these we see numbers and names. Computers can only work with numbers while people remember names better then numbers. That's why every name is associated with a number. Of course there is a way to map names to numbers and vice versa. To show how this is done, try:
apple:~ > grep leeuw /etc/passwd leeuw:x:514:100:Dennis Leeuw:/home/leeuw:/bin/bash
where you of course substitute leeuw with your own username. Do this also for /etc/group:
appel:~ > grep leeuw /etc/group writers:x:220:leeuw appel:~ > grep 100 /etc/group users:x:100:
Now it probably gets clearer. The /etc/passwd file shows that leeuw has user id 514 and belongs to group 100. Next the /etc/group shows that leeuw belongs to group writers and that group 100 is named users. Well we knew this already from the id command, but now we know why.
Going back to our little rights table:
Type | Owner | Group | Other |
d | rwx | rwx | rwx |
For each type of user (owner, group, other) you can assign three possible actions:
I think the read and write permissions are self explaining and execute probably too, except for one point: if you want to execute a program that program has first to be loaded from harddisk into memory. So it has to be read first, before it can be executed. You thus need the read permission too, and the same goes for directories, only for another reason. It is not useful to be able to enter a directory without being able to view it's contents, although it is sometimes used as a security meassure, people can access files if they know the path and filename by only setting the x, but they can not list files since they can not read the directory file (r).
A couple of examples to show you how it works:
appel:~ > mkdir test appel:~ > cd test appel:~/test > touch file1 appel:~/test > ls -al total 8 drwxr-xr-x 2 leeuw users 4096 May 8 15:44 . drwxr-x--- 43 leeuw users 4096 May 8 15:44 .. -rw-r--r-- 1 leeuw users 0 May 8 15:44 file1
file1 is created with ownership leeuw and group users, but let's assume that this file should belong to the group writers, the other group I belong to.
appel:~/test > chown leeuw.writers file1 appel:~/test > ls -al total 8 drwxr-xr-x 2 leeuw users 4096 May 8 15:44 . drwxr-x--- 43 leeuw users 4096 May 8 15:44 .. -rw-r--r-- 1 leeuw writers 0 May 8 15:44 file1According to the permissions the file is now read/write-able for me (the owner) and readable for the group writers and the world, this is not what we want. It should be editable by the co-writers, but should currently not be accessable to others, so we need to change these permissions. Where we used chown (change owner) for the ownership, we use chmod for the permissions. chmod understands a bit notation and a human readable notation. We are will start with the human readable one.
appel:~/test > chmod g+w file1 appel:~/test > ls -al total 8 drwxr-xr-x 2 leeuw users 4096 May 8 15:44 . drwxr-x--- 43 leeuw users 4096 May 8 15:44 .. -rw-rw-r-- 1 leeuw writers 0 May 8 15:44 file1 appel:~/test > chmod o-r file1 appel:~/test > ls -al total 8 drwxr-xr-x 2 leeuw users 4096 May 8 15:44 . drwxr-x--- 43 leeuw users 4096 May 8 15:44 .. -rw-rw---- 1 leeuw writers 0 May 8 15:44 file1
What we did was we assigned write permissions (+w) for the group (g) and after that we removed the read (-r) permissions for other (o).
The fact that everything is a file within a Unix system can create problems with directories and ideas about read-only files. Remember that deleting a file is not about the file, but about changing the content of the directory(file). Except for the content of a file, most changes to a file is about changes to the directory. Some unexpected situations might arise:
Since computers only understand numbers, what's then the trick with rwx?
Answer: they are converted to numbers. Actually the rwx-permissions are bits. So you are setting bits when setting permisions. If I have three bits for rwx, like 111. Or for r-x, you would have 101, but it would probably be clearer to explain this by a couple of examples.
The lowest bit is the x-bit and the highest the r-bit. That means that to set the x bit you'll have a 2^0 decimal value which is equal to 1, for the w bit you have 2^1 which is a decimal value of 2 and for the r-bit it comes to 2^2 which is 4.
By summation of the different values one can assign a setting per owner, group and other. That means that a chmod 750 file1 would assign rwxr-x--- to file1. The 7 is the owner rights which is composed of 4+2+1, the 5 is the group right which is composed of 4+1 and the 0 is the other right, which means no bit is set.
Now check for yourself what the chmod value for file1 should be for it's current setting of rw-rw----.
When we created file1, after the touch, we saw that it was created as user leeuw, with group users and a permission setting of rw-r--r--. There is some way the system has to know how to create a file with these settings. A system that creates default world-readable files is not what you want in a very security sensitive environment, in my case it is no problem, it is my workstation with just two accounts and no network connection, so I don't worry about it. But it might be wise to change the default behaviour.
When you login to your system a shell is started, on GNU/Linux systems this is usually bash, which reads a settings file called /etc/profile. In this file is an entry called umask. Try the following:
appel:~/test > cat /etc/profile| grep umask umask 022This might look a bit different on your system. My system umask is set to 022. The special think about umask is that it never sets the x-bit by default and the everything else is the inverse of the chmod decimals, so a 0 means rw and a 2 means r. What happens is that the umask is AND with 777 for directories and AND with 666 for files (where 777 and 666 are the "default" permissions when no umask is used) and creates the default permissions. So a umask of 027 creates rw-r----- as the default permissions. The easiest way to do the math is subtracting the umask setting from the default permissions.
If you want to experiment with this you could use the umask command, as used in your /etc/profile to change the default behaviour. Try the following and watch the results:
appel:~/test > umask 025 appel:~/test > touch test appel:~/test > umask 027 appel:~/test > touch test2 appel:~/test > ls -al total 8 drwxr-xr-x 2 leeuw users 4096 May 8 16:50 . drwxr-x--- 43 leeuw users 4096 May 8 15:44 .. -rw-rw---- 1 leeuw writers 0 May 8 15:44 file1 -rw-r---w- 1 leeuw users 0 May 8 16:50 test -rw-r----- 1 leeuw users 0 May 8 16:50 test2
Next to the rights mentioned there are some additional features that can be set. The triplet (777) is actually a quadlet. With the fourth or actually the first part one can set:
Use u+s or 4777 for the SUID bit.
Not used on GNU/Linux
The SUID bit sets the effective user under which an application is run. If for example you set the SUID bit on an application that is owned by root, and a normal user starts the program, the program will run with the rights of root. This can be handy to give users the ability to run some programs that would normally not be possible, but it might also create a security hole. So be careful.
An example is /usr/bin/passwd which allows users to change their own password, but also ping which needs to be able to read packets coming from an interface where normal users do not have the right to do so.
Use g+s or 2777 for the SGID bit.
If the SGID bit is set on a directory it means that the group name is inheritted by newly created files and the group plus the SGID bit is inheritted by directories under the directory with the SGID bit set.
The SGID bit sets the effective group under which an application is run. If for example you set the SGID bit on an application that is group owned by root, and a normal user starts the program, the program will run with the group rights of root. This can be handy to give users the ability to run some programs that would normally not be possible, but it might also create a security hole. So be careful.
The stick bit can be set with the -t option to chmod, or by using 1777. It's the 1 that indicates the sticky bit and this bit has a different meaning for files or directories.
When the sticky bit is set on a directory, only the item's owner, the directory's owner, or the superuser can rename or delete files within the directory.
Example usage: see the /tmp directory
Has no meaning in the Linux kernel
When you want to share data with other users one often creates a directory which is owned by the group (root.<groupname>). Setting the mode to 2770, means that the people of the group can create files and directories in that directory, but the others are not able to see what is in there. The sticky bit makes sure that newly created data belongs to the group.
All fine and well, but the umask for non User Personal Group systems is often set to 0022, which means files are created with rw-r--r--, meaning readable for the world. Not what you want. To change this we set the default umask to 0007. This would make newly created directories set to rwxrwx--- and newly created files rw-rw----, meaning that members of the group can access and change the data per default. (Another option is to set the default umask to 0027, which makes directories rwxr-x--- and files to rw-r-----.)
Within a persons personal (home) directory files are thus created with full access to the group the person belongs to. If the default group of a person is users that means that all users of system are able to change the personal and often private data. To prevent this from happening the User Personal Group idea came up. Which means that every person has a default group to which only he or she belongs. On most systems supporting UPG, the default group name is identical to the username. The home-directory is thus owned as <username>.<groupname> and has the access rigths set to 2770.
The Linux ext-filesystems have the ability to store extra attributes to a file. These are attributes that can be set on extN (ext2, ext3, ext4) file systems. The commands needed are: chattr and lsattr.
To list the attributes set on a file use:
lsattrThis lists all attributes of all file in a directory. For the attributes of a single file add the file name to above command.
With the chattr command you can change the attributes. The manual-page of chattr extensively documents the options that can be set and unset, here we will only provide you with some basic features:
BSD also has the ability to store attributes. The command on those systems, like Mac OS X, is chflags. Microsoft Windows has the attrib tool to change the file attributes.
The Microsoft attrib command knows four attributes:
Extended attributes have nothing to do with file rights and access, they are about providing additional information to a file (META-data). You can store <name>=<value> pairs.
The use of extended attributes is an ext-filesystem feature. So it is supported by ext2, ext3 and ext4. Normally only root is able to change the attributes, if you want users to be able to change the attributes on their files mount the file system with the user_xattr option. In fstab you could have something like this:
/dev/sda1 /home ext4 defaults,,acl,user_xattr 1 2
The extended attributes are stored in an additional inode, so the block-size depicts the amount of extended data that van be stored. If the block-size is 4K, one can store 4096 kilo bytes of extended attributes.
To provide additional information use:
setfattr -n user.place -v "Utrecht, Church, Dom" DC0000345.JPGOf course this information can better be stored in the EXIF field, but putting it in an extended attribute the data can be read faster then from the EXIF data.
To read the information use:
getfattr -n user.place DC0000345.JPG
Deleting can be done using the -x option:
setfattr -x user.place
Since version 2.5.46 of the Linux kernel in November 2002 GNU/Linux supports the use of ACLs (Access Control Lists). ACLs expand on the above explained concept to make access rights more complex, with the positive effect that you can have more and better control over who accesses which file. Assume that you have a file that is owned by user leeuw, the group ownership is for users and you want to give a user piet access to a file and piet is not part of the users group. In the old situation you could only create a special group for the two users to share their files or open the file for all others. With ACLs the solution is simple, just add piet to the ACL list with the rights that you want to give to him.
To add, modify or remove ACLs you use setfacl, and to show ACLs you use getfacl. But how do you know that a certain file or directory uses ACLs, since all the commands still show the -rwxrwxrwx security settings. Well that is not entirely true. If ACLs are set they will show up as a + sign:
drwxr-x--- 2 leeuw users 4096 2010-03-17 13:42 NoACLdir drwxrwx---+ 2 leeuw users 4096 2010-03-17 13:44 ACLdirAs you can see the last directory in the list has ACLs set.
As the name implies, an ACL is a list of access rights, the list is contructed of ACE's or Access Control Entries. If I do a getfacl on the ACLdir I get:
appel:~ > getfacl testdir # file: testdir/ACLdir/ # owner: leeuw # group: users user::rwx group::r-x group:writers:rwx mask::rwx other::---The lines prefixed with # are so called header files. With the --omit-header option you can create an output without these headers. Every other line shows an ACE.
The rights shown by a ls -l are represented by the user::, group:: and other:: ACEes. The colons (:) you see are field seperators. Meaning that every line consists of 3 fields. The first field is the type field, the second the name field and the third the rights field. Before we dive into this it might be better to look at some examples:
appel:~ > mkdir acldir appel:~ > getfacl --omit-headers acldir user::rwx group::r-x other::---This is a directory without any ACLs set. When we add another user (and please replace piet with a known user on your system):
appel:~ > setfacl -m user:piet:r-x acldir appel:~ > getfacl --omit-headers acldir user::rwx user:piet:r-x group::r-x mask::r-x other::---The user piet can now enter our directory and list its contents. The same we can do for groups:
appel:~ > setfacl -m group:writers:rwx acldir appel:~ > getfacl --omit-headers acldir user::rwx user:piet:r-x group::r-x group:writers:rwx mask::rwx other::---
As you might have noticed, when we added the user we automatically also got a mask line, and when we added the group it changed from r-x to rwx. This is because there is such a thing as effective and masked rights.
Effective rights are the actual rights you have on a file or directory. For the user and other entries in the ACL, then mentioned rights are always the effective rights. All other entries have a masked right, which means their effective rights are calculated through the use of the mask entry. The calculation is simple. Entries in the mask mask the effective rights, meaning that if we have the following example:
user:piet:r-x mask::rw-the effective rights for piet are read, since it own rights do not support write, and the mask says that execute is not supported.
Note that the mask has nothing to do with the umask. The umask is for the creation of files, while the mask is for access of the file.
Only directories can have Default ACLs, which act as rights inheritance, like the SGID bit described earlier. The rights are inherited on directories and files that are created under the directory with Default ACLs. Note that also the defaults are inherited with newly created directories. This is what most people coming from a Windows system expect since inheritance is the default on Microsoft operating systems, so when using SAMBA it might be handy to set the defaults on the directories you share. Your users then get what they expect.
To set the current settings of a directory as the defaults do:
getfacl --access acldir | setfacl -d -M- acldir
To set a single default add the -d option:
appel:~ > setfacl -d -m group:writers:rwx acldir appel:~ > getfacl acldir user::rwx user:piet:r-x group::r-x group:writers:rwx mask::rwx other::--- default:user::rwx default:group::r-x default:group:writers:rwx default:mask::rwx default:other::---As you can see there are 5 lines added describing the defaults for this directory. Every line starts with a default field followed by a default in the normal 3 field notation. With this you can describe how the inheritance should work for your situation.
By using -x instead of -m to setfacl you can remove a certain ACL.
setfacl -x user:piet acldirTo remove the default use -k:
setfacl -k acldirTo remove ACLs all together use -b:
setfacl -b acldir
When working with interoperability between different systems, file system access rights might create some confusion, especially when we are talking about network file systems like NFS and SMB.
This table is based on:
Function | UNIX | POSIX Draft ACLs | NFSv4 ACLs | Mac OS X | Windows |
---|---|---|---|---|---|
Read file | r | r | r | read | Read |
Write file | w | w | w | write | Write |
Append to data | w | w | a | append | Write |
Execute | rx | rx | rx | read & execute | Read & Execute |
Delete | w | w | d | delete | Modify |
Take Ownership | w | w | o | take ownership | Take Ownership |
Function | UNIX | POSIX Draft ACLs | NFSv4 ACLs | Mac OS X | Windows |
---|---|---|---|---|---|
List the contents | r | r | r | read | List Folder Contents |
Create file | w | w | w | write | Write |
Create sub-directory | w | w | a | append | Write |
Access files or subdirectories in a directory | x | x | x | execute |
We found out that Mac OS 10.9 needs the d bit set on NFSv4 ACLs to be able to rename folders. Files do not seem to need this bit set.
The mtime is the modify time. Whenever the data of the file is modified, or the file created, the modify time is changed. The mtime does not change when a file attribute is changed. The mtime can be manipulated by you using touch with the -t option.
The ctime is the change time of an inode. The ctime changes when a change to the inode of the file occurs, this means that a write of the file changes the ctime, but also when you change one of the attributes of the file like owner or the access rights. The ctime is managed by the system and can not be controlled by a user.
The atime is the file access time. The atime changes when a file is read. This means that opening a file with an editor changes the atime, but also the use of grep, cat, sed, head, tail or whatever changes the atime. A write to a file does not need to change the access time. Like echo "Add line" >> file.txt this adds an extra line to the file, but does not change the atime!