Wednesday, April 20, 2011

How to change default `umask' in Linux. File permissions for collaborative environment

Umask is a command and value that defines what permissions newly created files and directories will have. Had it not been for umask, every file you create would have had permissions set to 666 (u=rw,g=rw,o=rw), and every directory would have had 777 (u=rwx,g=rwx,o=rwx). But the value of umask is subtracted from 666 and the difference is used as the permissions for the new file. Usually, the default umask is 022, which leaves us with 644 (owner can read and write, others can read the file). The value of umask may be different for different users. This is done with the command of the same name (search for 'umask' in `man bash`).

Frankly, I find the choice of the default value for umask rather strange. Suppose you have a server where five people work on a web application and they have their own accounts. The code is stored in a version control system. These five people should have enough permissions to check out new code. When one of them adds a new file to the repository and then checks it out, the file belongs to this user and cannot be modified by the others. Solutions might be either to grant write permissions to everyone (chmod 666 filename) or to change the group ownership of the file to some group to which all five developers belong and grant write permissions to that group. The first solution is insecure. As for the second one, we can use a simple trick to maintain group ownership of all files in the project.

Among various permissions you can set with chmod there is one called setgid. When this bit is set on a directory, all files and directories created in this directory will have the same group ownership as this directory. So, we only have to grant write permissions to the group-owner in order to work in collaboration with other users. To grant the necessary permissions automatically, we could set the umask value to 002. This is done using simple command 'umask 002', but is there a way to set this as a default value for all users?

Umask may be modified in /etc/profile. For example, in Ubuntu Linux, this file contains the following line:

umask 022

By changing the value to 002, we'll change the umask for all users who log in using shells which execute /etc/profile. Watch out, though. There are some situations when this file is not run. For example, cron executes all commands using default umask 022. How do we tackle this problem?

Another way to change umask is to use PAM (Pluggable Authentication Modules), the subsystem for adding various features to login process. One of these modules is called pam_umask. It allows for setting default umask for all users. We have to enable this module for both interactive and non-interactive sessions. In Ubuntu, configuration files of PAM are stored in /etc/pam.d. Make sure you have module pam_umask installed (package libpam-modules) and edit two files, common-session and common-session-noninteractive, adding one line in the end of each of them:

session optional pam_umask.so umask=002

NB! If I understand correctly, you have to run pam-auth-update so PAM would reread the configuration.

CAVEAT 1: umask may be set in users' ~/.profile, so make sure it is not!

CAVEAT 2: There are some especially badly written programs that have umask hardcoded. Gnome is notorious for having such bugs (e.g., see bug #336214). My advice would be: do NOT use GDM or Nautilus. Or Gnome, or KDE, for that matter :).

So, to sum it up. To set up a collaborative environment, we have to:

  1. create a new group: addgroup team
  2. add users to this group: adduser user1 team
  3. create new directory: mkdir /var/www/project
  4. change group ownership for the directory: chgrp team /var/www/project
  5. change the permissions for the directory: chmod g+sw /var/www/project
  6. edit PAM config files, adding pam_umask.so.

Now, every file that user1 creates in /var/www/project will be writable for all users in the team

Pardon me for repeating myself, but I do find the default value of umask unreasonable. 022 is often explained by security concerns, but it does not allow the group members to edit the file, but instead grants read rights to everyone! I could understand, say, 027, which bans read access to those outside the group, or 002, which grants write access to the group. Perhaps, 007 would be a good compromise.