31

If I change the umask to 0000, I'd expect a text file to be created with rwxrwxrwx permissions (based on my understanding of the umask, as described in the "possible duplicate" question) However, when I try this, I get the following

$ umask 0000
$ touch /tmp/new.txt
$ ls -ld /tmp/new.txt 
-rw-rw-rw-  1 alanstorm  wheel  0 Jun  2 10:52 /tmp/new.txt

That is, execute permission is omitted, and I end up with rw-rw-rw- for files (directories are rwxrwxrwx). I tried this on my local OS X machine, an old BSD machine I have at a shared host, and a linux server running on linode.

Why is this? Its my understanding that umask is the final arbiter of permissions -- is my understanding of this incorrect? If so, what else influences the default permissions of files on a unix system?

Alana Storm
  • 1,453

3 Answers3

40

umask is subtractive, not prescriptive: permission bits set in umask are removed by default from modes specified by programs, but umask can't add permission bits. touch specifies mode 666 by default (the link is to the GNU implementation, but others behave in the same way; this is specified by POSIX), so the resulting file ends up with that masked by the current umask: in your case, since umask doesn't mask anything, the result is 666.

The mode of a file or directory is usually specified by the program which creates it; most system calls involved take a mode (e.g. open(2), creat(2), mkdir(2) all have a mode parameter; but fopen(2) doesn't, and uses mode 666). Unless the parent directory specifies a default ACL, the process's umask at the time of the call is used to mask the specified mode (bitwise mode & ~umask; effectively this subtracts each set of permissions in umask from the mode), so the umask can only reduce a mode, it can't increase it. If the parent directory specifies a default ACL, that's used instead of the umask: the resulting file permissions are the intersection of the mode specified by the creating program, and that specified by the default ACL.

POSIX specifies that the default mode should be 666 for files, 777 for directories; but this is just a documentation default (i.e., when reading POSIX, if a program or function doesn't specify a file or directory's mode, the default applies), and it's not enforced by the system. Generally speaking this means that POSIX-compliant tools specify mode 666 when creating a file, and mode 777 when creating a directory, and the umask is subtracted from that; but the system can't enforce this, because there are many legitimate reasons to use other modes and/or ignore umask:

  • compilers creating an executable try to produce a file with the executable bits set (they do apply umask though);
  • chmod(1) obviously specifies the mode depending on its parameters, and it ignores umask when "who" is specified, or the mode is fully specified (so chmod o+x ignores umask, as does chmod 777, but chmod +w applies umask);
  • tools which preserve permissions apply the appropriate mode and ignore umask: e.g. cp -p, tar -p;
  • tools which take a parameter fully specifying the mode also ignore umask: install --mode, mknod -m...

So you should think of umask as specifying the permission bits you don't want to see set by default, but be aware that this is just a request. You can't use it to specify permission bits you want to see set, only those you want to see unset. Furthermore, any process can change its umask anyway, using the umask(2) system call! The umask(2) system call is also the only POSIX-defined way for a process to find out its current umask (inherited from its parent). On Linux, starting with kernel 4.7, you can see a process's current umask by looking for Umask in /proc/${pid}/status.

(For the sake of completeness, I'll mention that the behaviour regarding setuid, setgid and sticky bits is system-dependent, and remote filesystems such as NFS can add their own twists.)

Stephen Kitt
  • 434,908
  • 1
    It doesn't matter touch or other tools, that's behavior came from the open() syscall and the default file mode. – cuonglm Jun 03 '16 at 16:00
  • 1
    @cuonglm, there is no default file mode, if O_CREAT or O_TMPFILE is included in the open() flags, then the mode must be specified (see the POSIX specification for open() or the open(2) manpage). If you look at the source code I linked to, you'll see that touch specifies the mode. – Stephen Kitt Jun 03 '16 at 16:26
  • Yes, there is. 777 for directory and 666 for file, you can read the link in my answer for more detail. – cuonglm Jun 03 '16 at 17:22
  • @cuonglm, seriously, there isn't, at least not for open(). Try a program running open("somefile", O_CREAT);, you'll get a file whose mode is whatever value was in memory on the stack — e.g. I got --wsr----- just now, with a umask of 022. If you change the call to open("somefile", O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); you'll get an executable file (assuming your umask allows it). – Stephen Kitt Jun 03 '16 at 18:35
  • @cuonglm I've clarified my answer; there is no default for open(), but there is one for fopen(). – Stephen Kitt Jun 04 '16 at 10:04
  • @Stephen Kitt What about built-in redirection? (echo a > f.txt) It also seems to ignore executable bit. – Thunderbeef Aug 31 '17 at 10:47
  • @Thunderbeef POSIX doesn’t mention permissions for redirection explicitly, so the defaults apply: files are created with mode 666, masked by umask, so the executable bit can’t be set when a file is created using redirection. (If f.txt already exists and is executable, echo a > f.txt won’t change that.) – Stephen Kitt Aug 31 '17 at 11:09
6

The formula to calculate your file permission:

default_mode & ~umask

(Read the description of O_CREAT flag)

Also specified by POSIX, the default mode for file is S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP | S_IRUSR | S_IWUSR or 666, the default mode for directory is S_IRWXU | S_IRWXG | S_IRWXO or 777 if it was not specified by application.

Since when the execution bits in file default mode are 0, perform bitwise AND & with 0 is always 0.

That's why whatever value of umask, your newly created files will have execution bits off if your application don't specify the execution bits.

cuonglm
  • 153,898
2

Above description is very good. It provides clear description of umask and permissions. To be more pratical, If you want to see, what are permissions provided by "touch" do

" strace touch /tmp/new.txt "

observe the system call used by touch to create "new.txt"

for ex. o/p of "strace touch /tmp/new.txt" (... -> some content)

...

open("/tmp/new.txt", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3

...

for reference strace