File permissions and umask in PHP and Shopware

Preposition

This post requires basic understanding of Unix File system permissions.

Permissions of new files and directories

Have you ever wondered how the permissions are chosen for newly created files and directories?

Let's assume the following example that creates a new directory named somedirectory and a new file called examplefile.

mkdir('somedirectory');
file_put_contents('examplefile', 'somedata')

What permissions will these files have?

Answer: It depends!

It depends on the processes umask environment.

What is the umask?

The umask is the file mode creation mask. The mask is applied with a bit wise operation whenever a file is created.

It is represented in logic notation as: C: (P&(~Q)) This says that the file's permission mode (C) is a result of a logical AND operation between the negation of the mask (Q), and the process' requested permission mode setting (P).

New files are requested with permission mode 666, directories with permission mode 777. Given we have a umask of 022 as octal value and we create a new file the following permissions are calculated:

Requested File permissions: 666 (P)
Umask: 022 (Q)
666 & ~(022) = 644 (C)

Examples

A umask 000 will allow read, write, and execute permission for all. This is a potential security risk and should not be used in production.

$ umask 000              # set umask
$ mkdir testdirectory    # create new directory
$ touch somefile         # create new empty file
$ ls -l                  # list file permissions
drwxrwxrwx testdirectory # 777 in octal
-rw-rw-rw- somefile      # 666 in octal
777 & ~(0) = 777
666 & ~(0) = 666

A umask 002 will allow allow read, write, and execute permission for the user and the group, others will only have read access.

$ umask 002
$ mkdir testdirectory
$ touch somefile
$ ls -l
drwxrwxr-x testdirectory # 775 in octal
-rw-rw-r-- somefile      # 664 in octal
777 & ~(002) = 775
666 & ~(002) = 664

umask 077 Is the most restrictive umask. Only the user has access to the generated files.

$ umask 077
$ mkdir testdirectory
$ touch somefile
$ ls -l
drwx------ testdirectory # 700 in octal
-rw------- somefile      # 600 in octal
777 & ~(077) = 700
666 & ~(077) = 600

Umask in PHP

PHP respects the umask even if the mkdir $mode parameter is set:

umask(0027) // set directly or by environment
$mode = 0775;
mkdir('somedirectory', $mode);

Given we have a umask of 027 this will result in the following permission:

775 & ~(027) = 750

PHPs chmod() on the other hand does not respect the umask.

umask(0027) // set directly or by environment
$mode = 0775;
chmod('somedirectory', $mode);

This will result in 775 permissions regardless of the umask setting of the process.

Umask in shopware

Shopware already respected the umask for some caches. Some other caches used hard coded permissions.

The Smarty Compile Cache for example used hard coded permission values:

// file engine/Library/Smarty/Smarty.class.php
public $_file_perms = 0644;
public $_dir_perms = 0771;

This is now changed to respect the umask:

// file engine/Library/Enlight/Template/Manager.php
$this->_file_perms = 0666 & ~umask();
$this->_dir_perms = 0777 & ~umask();

Also the permissions of cache files are now using the umask instead of hard coded permissions:

// file: engine/Shopware/Configs/Default.php
'cache' => [
    'backendOptions' => [
-          'hashed_directory_perm' => 0771,
-          'cache_file_perm' => 0644,
+          'hashed_directory_perm' => 0777 & ~umask(),
+          'cache_file_perm' => 0666 & ~umask(),
    ]
]

You can find all the changes in the Github Pull Request.

This changes will be included in the upcoming Shopware 5.1.4 release.

Setting the umask

Now that Shopware respects the umask for all cache files there no need to configure individual file creation permissions anymore. Just set the umask and Shopware will create files accordingly. The umask can be set in your Apache or PHP-FPM configuration, or by calling umask(0077); in you projects config.php.

Back to overview
Top