File Permissions
In Linux, each files has nine permission bits. There are three basic permissions, read (r), write (w) and execute (x), for a file. These three permissions are there for the owner (o) of the file, the group (g) set for the file and the “others” (o). The ls -l command displays the permission bits,
$ ls -l /sbin | head total 11072 -rwxr-xr-x 1 root root 5532 Oct 3 2012 acpi_available -rwxr-xr-x 1 root root 26756 Jun 13 2013 agetty -rwxr-xr-x 1 root root 5576 Feb 14 2013 alsa -rwxr-xr-x 1 root root 5544 Oct 3 2012 apm_available -rwxr-xr-x 1 root root 824376 Nov 13 2013 apparmor_parser -rwxr-xr-x 1 root root 22128 Jun 24 2013 badblocks -rwxr-xr-x 1 root root 30472 Jun 13 2013 blkid -rwxr-xr-x 1 root root 13824 Jun 13 2013 blockdev -rwxr-xr-x 1 root root 54928 Aug 19 2013 bridge
For each file, the permissions for the owner, group and others are listed. A dash (-) indicates that a particular permission is not there.
Permissions are often denoted by octal numbers, with 4, 2 and 1 numbers indicating the read, write and execute permissions respectively. For example, octal 755 indicates the read, write and execute permissions (7) for the owner of the file and the read and execute permissions (5) for the group and others. Using octal numbers presumes that the permissions are stored in the order: owner, group and others. It is possible to not to use this presumption and use symbolic values instead of octal numbers for setting the permissions. For example, in the following chmod commands,
$ chmod 755 foo $ ls -ls foo 4 -rwxr-xr-x 1 user1 user1 99 Jun 25 19:48 foo $ chmod 000 foo $ ls -ls foo 4 ---------- 1 user1 user1 99 Jun 25 19:48 foo $ chmod u=rwx,go=rx foo # equivalent to chmod 755 foo $ ls -ls foo 4 -rwxr-xr-x 1 user1 user1 99 Jun 25 19:48 foo
File creation and umask
A file is created by a process like shell, vim editor, etc. To create a new file, a process executes the creat or open system call,
#define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) if ((fd = creat ("foo", FILE_PERM) ) == -1) perror ("error in creat"); if ((fd = open ("bar", O_RDWR | O_CREAT | O_TRUNC | O_EXCL, FILE_PERM) ) == -1) perror ("error in open");
The above code snippet tries to create a file named foo with permission of read and write for the owner and read for the group and others.
A file permission symbol in C language is of the form S_Ipwww, where p, the permission, is r, w or x for read, write and execute respectively, and www is for whom, which can be USR, GRP, or OTH for user, group and others respectively. Thus we have nine symbols for permission, which can be OR‘ed to arrive at the permissions for a file.
Now, the file permissions are something that should be decided by the user at runtime and not by the distant programmer who has coded the program months (or, possibly, years) ago. So, we have the concept of umask which allows a user to have the final word on the file permissions. umask is an unsigned integer in a process's environment, having lower order nine bits corresponding to read, write and execute permission bits for the owner, group and others respectively and having higher order bits as zero. So no matter what permissions the programmer envisaged in his or her code for creating a file, the actual permissions that end up for the file are the AND of the permissions requested by the program and the complement of umask value. The reason why we have the complement of umask
before the AND is that if a bit is set in umask, it is cleared in the file permission. So a umask of 022 would clear the write bits of file permission for the group and others.
umask is a part of a process's environment that is preserved across exec family of system calls.
How to set umask
umask is set by the umask command, mostly from a shell initialization file like /etc/profile, $HOME/.profile or $HOME/.bashrc. If the umask command is put in /etc/profile, it is set globally for all users. On the other hand, if umask command is put in $HOME/.profile or $HOME/.bashrc file, it is set locally for the concerned user. Also, a user can set umask anytime by executing the umask command. The command syntax is,
umask [-p] [-S] [mode]
umask is an internal command of the shell. That way, whatever value you supply becomes a part of the shell and is passed on to new processes that are forked and exec’ed from the shell. By default, the mode is an octal number. if the -p option is used and the mode value is not supplied, umask prints output in a form which can be used as an input umask command. With the -S option, mode is accepted/printed in symbolic form.
$ umask 0022 $ umask -p umask 0022 $ umask -pS umask -S u=rwx,g=rx,o=rx $ umask 0022 $ umask -pS umask -S u=rwx,g=rx,o=rx
umask system call
There is a umask system call, using which one can set umask in a program.
#include <sys/types.h> #include <sys/stat.h> mode_t umask(mode_t mask);
The only reasonable use of the umask system call seems to be to implement the umask command in a shell.