Skip to content

Filesystem dumpFile creates file with chmod 0 because fileperms fails #54444

Closed
@ebuildy

Description

@ebuildy

Symfony version(s) affected

7

Description

Running Prestashop (it's use Symfony framework) on a very busy web site, after we clear cache (rm var/cache) from Prestashop admin, any HTTP call to Prestashop frontend create cache file using Symfony Filesystem dumpFile method.

Files created have a chmod 0, hence this gives fatal error "cannot include appParameters.php, permissions denied".

Affected version

Tested on Symfony 4 but should affect all versions.

Root cause

file_exists function will use opcache but fileperms not, so this code at https://github.com/symfony/symfony/blob/7.1/src/Symfony/Component/Filesystem/Filesystem.php#L665:

self::box('chmod', $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask());

Creates file with chmod 0

How to reproduce

With opcache settings:

opcache.validate_timestamps=0
opcache.enable_file_override=1

I use apache web server but this should work with nginx / php-fpm too.

  1. Create a file "existing.php", cache it in opcache: curl localhost/existing.php
  2. Create a bug.php, call it curl localhost/bug.php --> this is working as expected
  3. Remove existing.php file rm existing.php
  4. curl localhost/bug.php will create the file ----------. 1 www-data www-data 26 Mar 30 17:54 existing.php
Capture d’écran, le 2024-03-30 à 13 57 15

bug.php

<?php

require_once __DIR__.'/vendor/autoload.php';

use Symfony\Component\Filesystem\Filesystem;

$file = __DIR__ . '/existing.php';

echo "File $file" . PHP_EOL;

echo "File exists: " . strize(file_exists($file)) . PHP_EOL;

echo "fileperms: " . strize(fileperms($file)) . PHP_EOL;

(new Filesystem())->dumpFile($file, '<?php echo "hello world"; ');

function strize($bool): string {
    if ($bool === true) return 'true';
    if ($bool === false) return 'false';
    return $bool;
}

Possible Solution

In method https://github.com/symfony/symfony/blob/7.1/src/Symfony/Component/Filesystem/Filesystem.php#L665, use this code block to get the chmod:

        $chmod = 0666 & ~umask();

        if (file_exists($filename)) {
            $existingChmod = fileperms($filename);

            if ($existingChmod !== false) {
                $chmod = $existingChmod;
            }
        }

        chmod($tmpFile, $chmod);

clearstatcache(true, $file); didnt help.

Additional Context

Related issues:

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions