Permissions are a pillar of security. Because of this, an operating system (OS) should not only support filesystems with ways to store permissions but also provide mechanisms to handle them correctly in the kernel and modules around it. Thus, Linux has the umask command based on the umask() system call.
In this tutorial, we take a deep dive into umask and explore how to set a system-wide umask. First, we go over the way Linux handles default file permissions. Next, we extrapolate the usual base permissions set. After that, we check how umask augments these settings for new files. Finally, we enumerate ways to change the umask value globally.
For brevity, we use umask to mean both the actual mask and the command that handles it under Linux. Although the positions of permissions digits matter, they are taken as stand-alone numbers when we convert to other number systems.
2. Default File Permissions
When creating files, the OS typically assigns permissions based on a number of factors:
- user that issued the creation command
- context of the creation command
- creation command parameters
$ whoami baeldung $ touch file $ ls -l total 0 -rw-r--r-- 1 baeldung baeldung 0 May 05 06:56 file
Further, the permissions are -rw-r–r–, i.e., 000110100100 in binary or octal mode 0644.
Let’s find out how these are calculated.
3. Base Permission Set
In essence, mode 777 or rwxrwxrwx (111111111) is the maximum or most open permission set for any filesystem object. Further, mode 666 or rw-rw-rw- (110110110) allows world reads and writes only since the executable permission is a bonus.
However, we have several special permissions:
With the above, the final base permission set is 0666 or -rw-rw-rw- (000110110110).
In fact, we can verify this via strace as well:
$ strace touch file [...] openat(AT_FDCWD, "file", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3 [...]
The last argument, 0666, is the permissions to use or assign. It coincides with the base set above. Yet, as we saw earlier, the final permissions of the file are different.
4. umask Permission Modifications
In Linux, a umask is a way to reduce the permissions new files have.
$ umask 0022
Now, let’s perform the calculation Operation with the Base and umask permission modes, one by one, to get the Actual permissions of a new file in our case:
+---------------------------------------------------+ | Permission | Base | umask | Operation | Actual | |------------+------+-------+-----------------------| | Special | 0 | 0 | $(( 0 | 0 )) | 0 | | Read | 6 | 0 | $(( 6 | 0 )) | 6 | | Write | 6 | 2 | $(( 6 | 2 )) | 4 | | Execute | 6 | 2 | $(( 6 | 2 )) | 4 | +---------------------------------------------------+
Of course, we can perform this for any umask and Base to arrive at the correct umask value.
In general, to apply the value we decide on, we just use the umask command:
$ umask 0022 $ umask 0044 $ umask 0044
Yet, a reboot wipes this setting, so we’d have to ensure the last command runs on start-up using this approach. However, there are several mechanisms to avoid having to deal with hard-to-manage files.
5. System-Wide umask
Normally, a umask applies to the current process, user, and context. However, we can also set a global umask via a Pluggable Authentication Module (PAM).
Once enabled, this module looks for the umask value at several locations in order:
Let’s see how we can configure the module.
5.1. Install pam-modules
To have control over configuration important for the general system security, we usually install the pam-modules package:
$ apt-get install pam-modules
In this case, we use apt to do so. At this point, we can configure pluggable modules for different stages of the system utilization.
5.2. Enable pam_umask.so Module
For managing the umask with pam-modules, we check for a line in the /etc/pam.d/common-session configuration file:
$ cat /etc/pam.d/common-session [...] session optional pam_umask.so [...]
If the line above isn’t in the file, we can add it manually. This way, we ensure the pam_umask.so module is active. Otherwise, none of the settings below would be respected.
5.3. System-Wide Hard Default in /etc/pam.d/common-session
Actually, we can set a system-wide hard default value for umask by adding an option to the line in /etc/pam.d/common-session:
$ cat /etc/pam.d/common-session [...] session optional pam_umask.so umask=022 [...]
Now, any user or context in the system will start with a umask of 022. Using umask= this way sets the umask value permanently as long as there are no user-specific settings.
5.4. System-Wide Soft Default in /etc/default/login
To set a system-wide soft default, we can modify or create the /etc/default/login file with a UMASK= line:
$ cat /etc/pam.d/common-session [...] UMASK=024 [...]
Here, we use a value of 024 for the umask. This option has the least priority of all.
5.5. User Value in /etc/passwd
Using the additional information or GEneral Comprehensive Operating System (GECOS) field of a given user entry in the /etc/passwd file, we can also modify the umask:
$ cat /etc/passwd [...] baeldung:x:1000:1000:,,,umask=044:/home/baeldung:/bin/bash [...]
For example, adding umask=044 as above would ensure umask returns that value for that particular user (baeldung in this case). The /etc/passwd user field setting takes precedence over all the others, except setting umask manually via the umask command for a particular session.
Finally, we can modify the /etc/login.defs file with a UMASK line:
$ cat /etc/login.defs [...] UMASK 002 [...]
Here, we set a umask of 002. This value is considered only before the last resort: /etc/default/login.
In this article, we looked at the concept of a umask and how to configure its global value.
In conclusion, a umask is a critical security mechanism, so Linux provides several different ways to set it at different levels.