Wetin umask Dey Do for Linux Permissions
umask dey remove permission bits, e no dey grant access. Run umask, create file and directory, then see why root and your user fit show different modes.
Wetin umask dey do for Linux
umask na number wey every process for Linux carry, and e dey decide the mode of every file and directory wey that process create. Program dey ask kernel for some permissions when e dey create am. Kernel go clear every bit wey mask name, then apply wetin remain. umask no dey grant access at all. E only dey remove bits from wetin the program wey create am ask for.
This value no be property of your distribution. E depend on the account wey you dey use and how dem start the shell. These two answers fit differ for one machine, for the same time, even for stock image. So the first step no be to search manual. Na to measure am for the box wey dey front of you.
Print umask for the shell wey you dey use
umask
umask -SThe first form dey print the mask for octal. The second dey print the same mask as the permissions wey e allows, for the symbolic form wey chmod accepts. Leave both lines for screen. Everything wey follow na comparison against wetin your shell just print.
umask na shell builtin, e no be program wey dey disk. Confirm am with type umask. This matter because builtin dey change the shell process itself. Separate program fit only change e own process, then e go exit and carry the change comot.
Create file and directory, then read their modes
cd "$(mktemp -d)"
touch probe.file
mkdir probe.dir
stat -c '%a %A %n' probe.file probe.dir%a dey print mode for octal, while %A dey print the same mode for the drwxr-xr-x format wey ls -l dey use. Compare both lines with the mask wey you print small time ago. Every bit wey mask set dey missing from the modes, because na only clearing those bits mask dey do. If %A column never clear to read yet, the drwxr-xr-x permission string na the first thing wey you need understand well.
The file and directory no get the same mode, and mask no cause this difference. touch dey ask kernel for read and write for owner, group and other. mkdir dey ask for read, write and execute for all three. The same mask dey subtract from two different requests. So file wey touch create no fit ever get execute permission, no matter wetin mask contain: nobody request the execute bit, and mask no fit add bit back.
( umask a=rwx; touch open.file; stat -c '%a %A %n' open.file )Those parentheses dey run the commands inside subshell, so the change go disappear with the subshell. The mask now ask for nothing to clear, but stat still show say file no get execute bit. Run umask again afterwards and your original value go return. This show say the setting dey inside process and children dey inherit am; dem no store am for disk.
Na for directories you go really notice when execute bit clear.
( umask a=rw; mkdir noexec.dir; cd noexec.dir )As ordinary user, that cd go fail with bash: cd: noexec.dir: Permission denied, because mask clear the execute bit wey mkdir request, and directory without execute bit no fit enter. Root dey skip that check, so you go only see this for normal account.
Why root and your own user see different umask
Run the same measurement through another account, start am another way, then read the two outputs side by side.
umask
sudo -i umasksudo -i start root login shell and run the builtin command inside am, so na different account dey enter through different startup path. For standard Ubuntu and Debian server images, the two lines fit print different values. Both lines correct. Each one show wetin its own startup path produce, and the rest of this post dey explain which part of the system produce am.
Which file for your image decide the value
grep -nE '^(UMASK|USERGROUPS_ENAB)' /etc/login.defs
grep -rn pam_umask /etc/pam.d/
grep -rn umask /etc/profile /etc/profile.d/ /etc/bash.bashrc ~/.profile ~/.bashrc 2>/dev/null || echo 'no umask line in the shell startup files'If the first grep no print anything, run am again without the ^ anchor: the line fit dey commented out, and commented line na documentation, no be configuration. Na the third grep dey surprise people. For Debian and Ubuntu, the shipped /etc/profile mostly point to PAM instead of setting mask by itself, so the file wey you assume dey control am often no be the one. grep dey exit non-zero when e no match anything, na why that line end with || echo: for an image where no startup file mention mask, you go get the message instead of silence, and na the message be the finding.
/etc/login.defs dey advertise one value, and PAM dey apply another
The UMASK line for /etc/login.defs na the value wey most guides dey quote. Neither kernel nor shell dey read that file. Na pam_umask dey read am. pam_umask na PAM (pluggable authentication modules) module wey dey run when system create session. pam_umask dey take the first value wey e find: umask= entry for the user's GECOS field, then umask= argument wey dem write for pam_umask.so line itself, then UMASK from /etc/login.defs. Distributions fit patch this module, so run man pam_umask for your own image and read the order wey e print.
Na so /etc/login.defs fit advertise one value while your session end with another one, without any warning for either side. The greps go show you which case apply. If pam_umask.so line get im own umask= argument, the login.defs line don lose.
USERGROUPS_ENAB and the root exception
id -un
id -gnIf those two print the same name, you get a user private group: dem create the account with one group wey belong to am, and dem name the group after the account. pam_umask get one usergroups behaviour, and USERGROUPS_ENAB for /etc/login.defs dey control am. When e dey on, the account no be root, and the primary group name match the user name, the module copy the owner digit of the mask enter the group digit. The session go end with a mask wey leave the group bits open for everything wey that account create. The module exclude root by itself, and this exclusion na the most common single reason why two shells for one server fit print different masks.
The reason for this rule na say private group get exactly one member, so group-writable mean the same thing as owner-writable, and nothing more. This remain true until person add another member to the group. From that time, the new member fit write every file wey the account don ever create, and nobody run any command for those files to make am so. Give each service its own least-privilege user account and keep that group as group of one by intention.
Login shell, non-login shell and non-interactive shell
umask
bash -lc 'umask'
bash -c 'umask'PAM dey run when session dey create: login for console, sshd, su, sudo -i. E no dey run when one shell start another shell. bash -l na login shell, so e dey read /etc/profile and ~/.profile, but e no ever call pam_umask, because no session dey create. bash -c no dey read any of the two files and e inherit the mask of the process wey start am. Cron job, git hook, and program wey service manager start all dey for this last case, so dem mask na whatever their parent process get.
Na why report like "I set am for /etc/profile and the service still dey write wrong mode" common well-well. The service never read that file.
Wey to set am so e go survive
Set the mask for the place wey workload actually dey start from, because each start path dey read different file.
- For accounts wey dey log in:
UMASKfor/etc/login.defs, applied by pam_umask to every session for the machine. E affect the whole machine, so e go move every account at once. - For one account: the
umask=argument for thepam_umask.soline dey affect the whole machine too, so put per-user value for that user GECOS field, or for~/.profilefor login shells and~/.bashrcfor interactive ones. - For daemon under systemd:
UMask=for the unit[Service]section. Service manager dey start unit, so/etc/profileno dey read and pam_umask no dey run. Na only the unit file among these ones wey fit reach the daemon. - For script wey cron or hook start: put explicit
umaskfor the first line, before the script create anything.
[Service]
UMask=<the octal mask you chose>Then verify am from fresh start of that same path, and never use the shell wey you edit the file from. Your current shell don already hold its mask, and editing config file no fit affect process wey dey run already.
bash -lc 'umask'
sudo -i umaskWhy chmod afterwards no be the same fix
chmod dey repair files wey already exist. The mask dey decide the mode of files wey never exist yet. Run chmod -R for one directory, and the next file wey the service write go come with the old mode again, because na the creating process give am that mode, and nothing about the directory dey change am.
Window dey too. Between the time file dey created and the time chmod run, the file dey disk with the wider mode. Any process wey fit read the directory fit open am. For private key or backup archive, na that window be the risk wey you dey try remove.
Set the mode when you create the file instead. install -m u=rw,go= newfile /etc/app/newfile dey write the destination with explicit mode, and mkdir -m dey do the same for directory. Both dey use the mode wey you name and ignore the mask. ssh-keygen dey set the mode on the private key wey e write. Na why that one file often correct for machine wey everything else no correct.
SSH na the common victim. A ~/.ssh wey you make with plain mkdir, or an authorized_keys wey you append with cat >>, dey use the mask of your shell. When StrictModes dey enabled, sshd go refuse to read key file from directory wey group fit write. The client go see Permission denied (publickey), while the server /var/log/auth.log go record the real cause:
Authentication refused: bad ownership or modes for directory /home/deploy/.sshThat check na deliberate. Hardening SSH for one VPS depend on am to work. Measure the mask for new server before you create the accounts wey go use am, together with the first ten minutes for new VPS. This way, you don settle the mode of every file those accounts go write before time.
Copies and archives no dey follow mask
cp -p and rsync -a dey restore the mode wey dem record for the source file, so mask no get any say for the final result. tar do the same thing when e extract as root, or as ordinary user with -p. File wey you restore from backup go keep the mode wey e get when dem make the backup. Check this before you conclude say correct mask no dey work: for restored data, dem never consult am.
FAQ
Why cron job dey create files with different mode from my ssh session?
Cron job no be login session, so pam_umask no dey run for am, and e no dey read /etc/profile or ~/.profile. E inherit the mask from the process wey start am. Put explicit umask for the first line of the script, before e create anything. Print the mask once from inside the job too, so you fit see the mask wey that job really get, instead of the one wey your own shell get.
Why /etc/login.defs dey talk one thing and my shell dey print another?
UMASK for /etc/login.defs na only the last fallback for pam_umask. The module first prefer umask= entry for the user GECOS field. After that, e check umask= argument for the pam_umask.so line inside /etc/pam.d/. The usergroups behaviour, wey USERGROUPS_ENAB switch on, then change the group digit for any non-root account wey primary group get the same name as the account. Run grep -rn pam_umask /etc/pam.d/ and id -un; id -gn to see which one apply to your account.
Umask fit make file executable?
No. Mask fit only clear bits from the permissions wey the program wey create the file request. touch no dey request execute bit, so no mask fit produce executable file. Confirm am inside temporary directory with ( umask a=rwx; touch f; stat -c '%a %A' f ). To get execute bit, you need chmod, or program like install -m wey request am when e create the file.
Where I go set umask for systemd service?
For the unit, use UMask= inside the [Service] section. Service manager dey start service, no be login session, so e no dey read shell startup files and pam_umask no dey run for am. After systemctl daemon-reload and restart the unit, confirm am from outside: make the service create file, then read the result with stat -c '%a %n'.
Group-writable default mask safe?
E safe as long as the group get exactly one member. Na this assumption user private group scheme dey use. If you add another account to that group, every file wey the first account create go immediately become writable by the new member. You no need run any command on those files. Run id -un and id -gn: if dem print the same name, e mean say you dey use private group. If different accounts share one group, set mask wey clear group write bit. Then create file and read stat -c '%a %n' to confirm say the change work.