Rights on files

Inheriting your rights

© 2010-2013 Dennis Leeuw dleeuw at made-it dot com
License: GPLv2 or later


    1. Introduction
    2. Files and Special Files
      1. Links and directories
    3. Who am I
    4. Permissions
      1. WARNING: Everything is a file
      2. Working with numbers
      3. Default create mode
    5. The 4th bit
      1. The SUID bit
      2. The SGID bit
      3. The Sticky bit
    6. User Personal Group setup
    7. Attributes
      1. Simple attributes
      2. Extended attributes
    8. POSIX Access Control Lists
      1. The ACL mask
      2. Default ACLs
      3. Removing ACLs
    9. File Access Interoperability
      1. File system comparison
      2. Known issues
    10. File times
      1. mtime
      2. ctime
      3. atime


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.

Files and Special Files

Despite the fact that everything is file, there are some special files. Something like: some are more equal then others. The different types that are known to Linux are:

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 tools
Here 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 Type field shows the type of file we are talking about. To distinguish a directory from a "real" file the first field shows a d for directory and a - (dash) for a file. All available types are:
normal file
symbolic link
block device
character device

Links and directories

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.

Who am I

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
and 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 
appel:~ > grep 100 /etc/group

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
we still need to cover the rights for Owner, Group and Other. As we have seen Unix-like systems have two ways of identifying people. First the username and second the group to which they belong. Everything else is called the other. This way of identifying people is reflected in the way permissions are given. You can give permission on a owner-basis, group-basis and other-basis. Of course the owner-rights are stronger then the groups-rights, which are then again stronger then that of other.

For each type of user (owner, group, other) you can assign three possible actions:

read (r)
This indicates if a file can be read by a user
write (w)
Determens if you have the ability to write to a file
execute (x)
This gives you the ability to execute (run) a program or to enter a directory.

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 file1
According 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).

WARNING: Everything is a file

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:

Working with numbers

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----.

Default create mode

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 022
This 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

The 4th bit

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:

The SUID bit

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.

The SGID bit

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 Sticky bit

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

User Personal Group setup

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.


Simple attributes

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:

This 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:

If set the atime on a file will not be changed. This reduces the amount of disk I/O, which helps battery life on laptops.
If the a-bit is set, the file can only be opened in append mode. No changes can be done to the file except the adding of data. This could be useful for log files.
Data with the c option set is automatically compressed and decompressed by the kernel, before the data is written of after it is read from disk.
This sets (or unsets) the immutable bit. A normal user can only set this attribute when using sudo. So using sudo chattr +i filename will set the immutable bit. With the immutable bit set, even root is not allowed to remove the file.

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

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.JPG
Of 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

POSIX Access Control Lists

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 ACLdir
As 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
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
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
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

The ACL mask

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:

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.

Default ACLs

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
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.

Removing ACLs

By using -x instead of -m to setfacl you can remove a certain ACL.

setfacl -x user:piet acldir
To remove the default use -k:
setfacl -k acldir
To remove ACLs all together use -b:
setfacl -b acldir

File Access Interoperability

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.

File system comparison

This table is based on:

The NFSv4 ACLs column below describes the letters that need to be set by the nfs4_setfacl command as implemented on GNU/Linux.
File functions
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
Directory functions
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  

Known issues

File times


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!