How does umask affect ACLs?

I found this example, titled: ACL and MASK in linux. In this article the following examples are demonstrated which I think help to understand how ACL's and umask interact with each other.

Background

When a file is created on a Linux system the default permissions 0666 are applied whereas when a directory is created the default permissions 0777 are applied.

example 1 - file

Suppose we set our umask to 077 and touch a file. We can use strace to see what's actually happening when we do this:

$ umask 077; strace -eopen touch testfile 2>&1 | tail -1; ls -l testfile
open("testfile", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3
-rw-------. 1 root root 0 Sep 4 15:25 testfile

In this example we can see that the system call open() is made with the permissions 0666, however when the umask 077 is then applied by the kernel the following permissions are removed (---rwxrwx) and we're left with rw------- aka 0600.

example - 2 directory

The same concept can be applied to directories, except that instead of the default permissions being 0666, they're 0777.

$ umask 022; strace -emkdir mkdir testdir; ls -ld testdir
mkdir("testdir", 0777)                  = 0
drwxr-xr-x 2 saml saml 4096 Jul  9 10:55 testdir

This time we're using the mkdir command. The mkdir command then called the system call mkdir(). In the above example we can see that the mkdir command called the mkdir() system call with the defaul permissions 0777 (rwxrwxrwx). This time with a umask of 022 the following permissions are removed (----w--w-), so we're left with 0755 (rwxr-xr-x) when the directories created.

example 3 (Applying default ACL)

Now let's create a directory and demonstrate what happens when the default ACL is applied to it along with a file inside it.

$ mkdir acldir
$ sudo strace -s 128 -fvTttto luv setfacl -m d:u:nginx:rwx,u:nginx:rwx acldir

$ getfacl --all-effective acldir
# file: acldir
# owner: saml
# group: saml
user::rwx
user:nginx:rwx          #effective:rwx
group::r-x          #effective:r-x
mask::rwx
other::r-x
default:user::rwx
default:user:nginx:rwx      #effective:rwx
default:group::r-x      #effective:r-x
default:mask::rwx
default:other::r-x

Now let's create the file, aclfile:

$ strace -s 128 -fvTttto luvly touch acldir/aclfile

# view the results of this command in the log file "luvly"
$ less luvly

Now get permissions of newly created file:

$ getfacl --all-effective acldir/aclfile 
# file: acldir/aclfile
# owner: saml
# group: saml
user::rw-
user:nginx:rwx          #effective:rw-
group::r-x          #effective:r--
mask::rw-
other::r--

Notice the mask, mask::rw-. Why isn't it mask::rwx just like when the directory was created?

Check the luvly log file to see what default permissions were used for the file's creation:

$ less luvly |grep open |tail -1
10006 1373382808.176797 open("acldir/aclfile", O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666) = 3 <0.000060>

This is where it get's a little confusing. With the mask set to rwx when the directory was created, you'd expect the same behavior for the creation of the file, but it doesn't work that way. It's because the kernel is calling the open() function with the default permissions of 0666.

To summarize

  • Files won't get execute permission (masking or effective). Doesn't matter which method we use: ACL, umask, or mask & ACL.
  • Directories can get execute permissions, but it depends on how the masking field is set.
  • The only way to set execute permissions for a file which is under ACL permissions is to manually set them using chmod.

References

  • acl man page

for security purposes, the linux operating system doesn't allow for the automatic creation of a file with an execute bit. This is to prevent cyber attackers from writing programs into such files and executing them if they gain access to your server. It's just a safety precaution. You'll forever have to manually set the execute bit on files after creating them with the chmod utility