Skip to content

umask: How New File and Directory Permissions Are Set

A plain file created with touch report.txt in a terminal almost always comes out as -rw-r--r-- (644), and a new directory as drwxr-xr-x (755). Neither touch nor mkdir chose those numbers, and they are not arbitrary — they come from a value called umask attached to every process. Not understanding umask leads to two opposite mistakes: a sensitive file unexpectedly becomes world-readable, or files a service writes never end up group-writable when they need to be.

Special Permissions covered how setuid, setgid, and the sticky bit change an existing file's metadata. umask answers a different question: before an object even exists, what starting permission does it get? chmod corrects an existing file; umask prevents a new one from being born with the wrong permission in the first place.

Here you will see that a regular file starts from a base of 666 and a directory from 777; that umask works through a bitwise AND NOT, not subtraction; how to read umask and umask -S, and change the current value safely; where the mask is actually set — the shell, login.defs, PAM, or a systemd unit — and how to control a service's file permissions with UMask= or an interactive umask. Throughout, keep umask clearly separate from chmod, ownership, and a setgid directory.

Lab Setup

All the examples below work inside the current user's home directory and do not need sudo. umask only affects the current shell process and its children — it never touches system directories. Start each line exactly at the command; the $ or # prompt character is not part of it.

mkdir -p ~/lab/umask
cd ~/lab/umask
umask
umask -S

A representative result, which varies by system and distribution:

0022
u=rwx,g=rx,o=rx

The first line prints the current umask in octal; the second shows, symbolically, the permissions that are kept at creation time. On an ordinary Ubuntu Server user, this value is commonly 0022 or 0002 — the second is tied to a "user private group" policy, covered in User and Group Accounts.

Note

umask is not a separate program — it is a shell built-in. Because it is a process-specific attribute, its value only applies to the current shell and whatever it spawns afterward. A new terminal window or a new login session starts fresh, reading whatever value its configuration files supply.

The Base Permission and What the Mask Means

When a new object is created, the calling program decides what permission to request from the kernel, but in practice two common bases are used:

  • most programs request 0666 (rw-rw-rw-) for a regular file;
  • mkdir requests 0777 (rwxrwxrwx) for a directory.

Notice that the file base has no x bit at all. A regular file should not accidentally become executable — the execute bit is something you add deliberately with chmod when it is actually needed. A directory's base includes x because it means "enter."

umask decides which bits to remove from that base. It can only restrict, never add. The final permission is not arithmetic subtraction — it is a bitwise "AND NOT":

final_mode = base_mode AND NOT umask

In other words, every bit set in umask is cleared in the result; every other bit stays as it was in the base.

Why Not Subtraction?

Many guides simplify umask as "subtracted from the base." That gives the right answer most of the time, but it describes the mechanism incorrectly and produces a wrong result for some values. It is easiest to see with the bits themselves. Take mask 0023:

base (file): 110 110 110   = 0666
umask 0023 : 000 010 011
AND NOT    : 110 100 100   = 0644

For each triplet, a bit set in umask becomes 0 in the result; other bits are unchanged. Group w (010) and other's w and x (011) are cleared. The result is 0644. If this really were subtraction, 0666 − 0023 would equal 0643 — granting other a nonsensical -wx. So umask does not subtract — it masks out matching bits.

A file's base having no x also has a further consequence: umask's x bits never affect a regular file. umask 0111 leaves a file's 0666 unchanged, because the x bits it would clear are already absent from the base. The same mask does affect a directory, because the directory's base includes x.

Three Common Values

umask File result Directory result When
022 644 (rw-r--r--) 755 (rwxr-xr-x) others can read; the default on many systems
002 664 (rw-rw-r--) 775 (rwxrwxr-x) group members can write; useful for team work
077 600 (rw-------) 700 (rwx------) only the owner has access; suited to sensitive data

077 clears every group and other bit, so new files are only open to their owner. This is a safe default for a session that creates secrets or personal data frequently.

Testing It Directly

Now change the value and watch the result directly. umask 0027 leaves the group able to read, and clears everything for other:

umask 0027
umask
touch fileA
mkdir dirA
stat -c '%A %a %n' fileA dirA

Expected result:

0027
-rw-r----- 640 fileA
drwxr-x--- 750 dirA

The file's base was 0666; 0027 cleared group w and other rwx, leaving 0640. The directory's base was 0777; the same mask left 0750. Now try a stricter mask:

umask 0077
touch fileB
mkdir dirB
stat -c '%A %a %n' fileB dirB
-rw------- 600 fileB
drwx------ 700 dirB

Warning

These examples only changed umask temporarily, for the current interactive shell. The value disappears when that shell closes. Changing a global umask in /etc/profile, /etc/login.defs, or a systemd unit affects the whole system or an entire service — test it in a lab environment first.

Fixing an Existing File with chmod

umask only applies at creation time. It does not recompute an existing file — chmod is needed for that:

chmod 0644 fileB
stat -c '%A %a %n' fileB

umask is prevention; chmod is correction. The right umask keeps files from starting out with a wrong permission; chmod fixes an object that was already created incorrectly, or that needs a special mode. Neither one substitutes for the other.

What umask Does Not Affect

umask governs only one part of the permission model. Do not confuse it with these neighboring ideas:

  • Ownership. A new object's owner and group come from the creating process and any setgid directory policy, not from umask — covered in Ownership.
  • Special bits. umask does not automatically place setuid, setgid, or the sticky bit on a new object; those come from chmod or setgid inheritance, as in Special Permissions.
  • Existing files. As shown above, the mask only affects creation.
  • cp and archives. cp -p, cp -a, tar, and similar tools may try to preserve source permissions, bypassing umask entirely. After a copy or restore, check permissions with stat rather than trusting umask.

A setgid Directory and umask Together

In a shared directory, setgid makes new files inherit the directory's group, but it does not by itself grant group write access. That access still depends on umask. Suppose a setgid directory exists, but the session is running with umask 0022:

umask 0022
mkdir team
chmod 2775 team
touch team/report.txt
stat -c '%A %a %U:%G %n' team team/report.txt

Even though the directory is setgid, the file comes out 0644 — a group member can read it, but not write to it. If group write is required, the session needs umask 0002 instead:

umask 0002
touch team/report2.txt
stat -c '%A %a %U:%G %n' team/report2.txt

Now the file comes out 0664. The conclusion: "files in the team directory are not group-writable" is often caused not by a missing setgid, but by the wrong umask.

Where umask Comes From and How It Is Kept

umask is inherited from process to process, so "where is it set" matters. The main sources are:

  1. Shell built-in. An interactive umask 0027 affects only the current shell and its children. Writing it into a user's profile (~/.bashrc, ~/.profile) makes it persistent, but only for that user's interactive shell.
  2. /etc/login.defs. The UMASK directive sets the default mask applied during login.
  3. PAM (pam_umask). Many distributions set the login session's mask through a PAM module, which may choose a value based on login.defs or the user's group.
  4. systemd. For a service or the user manager, the mask is set explicitly with the UMask= directive in a unit file — the most reliable method for daemon-created files.

Always check the actual current session's value directly — do not assume the effective value just because a configuration file says so:

umask
grep -i '^UMASK' /etc/login.defs

grep only shows the text in login.defs; it does not account for a later override by PAM or a shell profile. The final proof is always the output of the umask command itself.

Note

On Ubuntu and Debian, an ordinary user often belongs to their own private group (for example, ali:ali). Because of that, umask 0002 is considered a safe default: group write in practice only applies to the user themselves. The RHEL family follows a similar "user private group" approach. In a shared, multi-member group, apply 0002 deliberately, after checking the group's actual policy.

Practical Scenario: Service Files Are Created Too Openly

Suppose report.service writes report files into /var/lib/report/out/. An audit found these files at 0644 — readable by any local user on the system. Policy requires only the service owner and the report group to view the reports. The cause is the service's umask, which is 0022.

This is a production change to a systemd unit. Do not proceed without a VM snapshot or configuration management, and a rollback plan.

1. Check the Current State Without Changing Anything

systemctl show -p User -p Group -p UMask report.service
sudo find /var/lib/report/out -xdev -type f -printf '%m %u:%g %p\n' | head
systemctl cat report.service

systemctl show reports the service's effective UMask; find shows the actual mode of existing files. If UMask is empty or 0022, it explains why new files come out 0644.

2. Determine the Intended Policy

Files should be readable by the owner and group, closed to everyone else. umask 0027 fits: group read stays, every bit is cleared for other. If group write is also needed, 0007 is the choice.

3. Backup and a Controlled Change

First save or note the existing drop-in, then set UMask through a drop-in file:

sudo systemctl edit report.service

In the editor that opens, add only this:

[Service]
UMask=0027

systemctl edit creates the drop-in /etc/systemd/system/report.service.d/override.conf and does not touch the main unit. This makes rollback simple: removing the drop-in is enough.

4. Reload and Verify

sudo systemctl daemon-reload
sudo systemctl restart report.service
systemctl show -p UMask report.service

Once UMask=0027 is confirmed, check the next report the service creates:

sudo find /var/lib/report/out -xdev -type f -newermt '-5 min' \
    -printf '%m %u:%g %p\n'

New files should come out 0640. Existing files keep their old mode — correct them separately with chmod, matching policy, only after a backup plan is confirmed.

5. Rollback

If the change has an unexpected effect, remove the drop-in:

sudo systemctl revert report.service
sudo systemctl daemon-reload
sudo systemctl restart report.service
systemctl show -p UMask report.service

systemctl revert undoes drop-ins created by systemctl edit and returns the service to its distribution-provided state. Check the service logs and new file modes again afterward.

Common Mistakes

Thinking umask Adds Permission

umask only removes bits. umask 0000 does not add x to a file's base — a regular file is still created at 0666. Use chmod when an execute or special bit is actually needed.

Treating umask as Arithmetic Subtraction

0666 − umask gives the right answer for many values, but the mechanism is a bitwise AND NOT. umask 0023 gives 0644 for a file, not 0643. When in doubt, confirm the result with stat.

Expecting the Same Result for a File and a Directory

The same mask affects a file's base (0666) and a directory's base (0777) differently. umask's x bits never touch a file, but they do affect a directory. That is why umask 0022 gives a file 0644 and a directory 0755.

Checking a Global umask with an Interactive One

Your login shell's umask does not show a service's or a cron job's mask. Check each context separately: systemctl show -p UMask for a service, and an explicit umask output inside a cron job.

Blaming a Shared Directory's Permission Problem Only on setgid

If files are not group-writable, the cause is often umask 0022, not a missing setgid. setgid inherits the group; umask controls the write bit. Fix both together.

Treating a Configuration File as the Effective Value

The UMASK value in /etc/login.defs is one source, not the single source of truth. PAM, a shell profile, or systemd can override it. Confirm the final value only by running umask in the exact context that matters.

Exercises

  1. Record the current umask with umask and umask -S. Then set 0022, 0002, 0027, and 0077 in turn, creating one file and one directory each time. From stat -c '%A %a %n' output, explain which bits each mask removed.
  2. Set umask 0111 and create one file and one directory. Explain, at the bit level, why the file's mode did not change while the directory's did.
  3. Create a setgid directory (chmod 2775). Compare the mode of a new file inside it under umask 0022 versus umask 0002. Show which mask actually allows group write.
  4. Compare the output of grep -i '^UMASK' /etc/login.defs against the umask command's own result. If they differ, determine which source — shell profile or PAM — set the effective value.
  5. For a hypothetical service, take the requirement that files should be readable only by the owner and group. Choose the matching umask, describe how you would set it as UMask=, and which command verifies the result. Do not change a real service.

Verification criterion: in every answer, show the base (0666/0777), the mask, and the three-step AND NOT operation — not just the final mode number.

When you finish the lab, inspect the target read-only:

find ~/lab/umask -xdev -maxdepth 2 -printf '%y %m %p\n'

Only if the result shows nothing but the ~/lab/umask test tree:

rm -rI -- ~/lab/umask

Warning

rm -rI deletes the test tree with no undo mechanism. Run it only after confirming the absolute boundary with the find command above. Save any results you want to keep elsewhere first; do not use this command on a production directory.

References

  • Linux man-pages: umask(2): https://man7.org/linux/man-pages/man2/umask.2.html
  • POSIX.1-2024: the umask utility: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/umask.html
  • Linux man-pages: open(2): https://man7.org/linux/man-pages/man2/open.2.html
  • Linux man-pages: login.defs(5): https://man7.org/linux/man-pages/man5/login.defs.5.html
  • Linux man-pages: pam_umask(8): https://man7.org/linux/man-pages/man8/pam_umask.8.html
  • systemd: systemd.exec(5) (UMask=): https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html
  • GNU Bash Reference Manual: Bourne shell builtins (umask): https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html