15

This question already has an answer here:

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?

marked as duplicate by Thomas Dickey, cas, don_crissti, Anthon, garethTheRed Jun 4 '16 at 20:07

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • `umask does not specify the mode, it masks it. like when you mask something before painting. It dose not force the paint to land everywhere else, it only blocks it from landing where the mask is. – ctrl-alt-delor Jun 3 '16 at 17:56
  • Note that if you're looking for a command that will leave the executable bits, the easiest way (in my opinion) is $ umask 0000 ; # no output ; $ touch /tmp/new.txt && chmod a+x /tmp/new.txt ; # no output ; $ ls -ld /tmp/new.txt ; -rwxrwxrwx 1 me my_group 0 Sep 18 18:29 /tmp/new.txt # <-output – bballdave025 Sep 19 '18 at 0:31
22

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.)

  • 1
    It doesn't matter touch or other tools, that's behavior came from the open() syscall and the default file mode. – cuonglm Jun 3 '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 3 '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 3 '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 3 '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 4 '16 at 10:04
5

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.

  • @StephenKitt: Run the strace, you can see the compiler call chmod() syscall, at least with gcc, clang. – cuonglm Jun 3 '16 at 17:19
  • I stand corrected, the compiler does indeed chmod(); but it is possible to create an executable using only an open() call. – Stephen Kitt Jun 3 '16 at 18:40
  • Actually compiler behaviour depends on the linker; if you use gold, it open()s the target file with the appropriate mode, it doesn't use chmod(). – Stephen Kitt Jun 3 '16 at 18:50
  • 1
    @StephenKitt I think the reason gcc does a chmod at the end is that if the production of the file fails midway, it doesn't do the chmod, so you don't end up with an incomplete executable. You're perfectly right that it isn't because it can't: it could if it specified the execute bits in umask, like mkdir does. – Gilles Jun 3 '16 at 22:05
1

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.