Skip to content

bug #14246 [Filesystem] dumpFile() negates default file permissions #17063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 7, 2016
Merged

bug #14246 [Filesystem] dumpFile() negates default file permissions #17063

merged 1 commit into from
Jan 7, 2016

Conversation

hboomsma
Copy link

Q A
Bug fix? yes
New feature? no
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #14246
License MIT
Doc PR none

Remain BC compatible with Symfony 2.8.
Without this change a chmod is needed after calling dumpFile, making it non atomic.

@@ -523,6 +523,7 @@ public function dumpFile($filename, $content)
}

$tmpFile = $this->tempnam($dir, basename($filename));
$this->chmod($tmpFile, 0666, umask());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apply the mode change after writing to the file, the umask may remove the write permission.

@linaori
Copy link
Contributor

linaori commented Dec 30, 2015

If I understand it correctly, there has been a deprecation added in 2.8 which was never merged into 3.0 and the code was never fixed properly there. If you take a look at the history of Filesystem.php:

  • The 3rd option is marked as deprecated
  • The default value is 0666
  • If the value is not null, it will set the permissions
  • By passing 2 arguments you will not trigger the deprecation notice but it will still set the permissions to 0666

This means that the only case where no permissions would be set, would be by passing null as third argument which was deprecated, but that's the exact behavior 3.0 has right now.

When you take a look at the 3.0 Filesystem.php, you can see that the permissions are not longer fixed. The only non-deprecated way, which is setting it 0666 afterwards is broken in 3.0.

/cc @xabbuh

@xabbuh
Copy link
Member

xabbuh commented Dec 30, 2015

@iltar I think your reasoning is correct and we need to always set the permissions as proposed here.

By the way, the solution before Symfony 3.0 was not really atomic, was it? I mean the chmod() call was done after renaming the file. Shouldn't this happened the other way around (like proposed here)?

@hboomsma
Copy link
Author

@iltar, this is indeed the case.

Code that ran in 2.8 without any deprication message stops working in 3.0 because the tempnam function of php creates files with access permissions set to 0600. In 2.8 this was fixed by running a chmod with 0666 (ignoring system umask). In 3.0 however, nothing is done and only the creating user can read the file.

@hboomsma
Copy link
Author

@xabbuh I agree that the permissions should be changed after writing as @cs278 pointed out and before renaming to make this operation atomic.

@xabbuh
Copy link
Member

xabbuh commented Dec 30, 2015

@hboomsma Would you like to create a pull request for older Symfony versions that swaps the order of the calls?

@hboomsma
Copy link
Author

@xabbuh sure, which versions should we patch? I'll create a pull request for 2.8 right away.

@xabbuh
Copy link
Member

xabbuh commented Dec 30, 2015

Hm, I think we will get other issues when merging this on filesystems that don't allow to change permissions (see #8205).

@hboomsma
Copy link
Author

@xabbuh you are right, I'll fix it in the same way, it was fixed in the mentioned issue, because if chmod is not supported tempnam will not mess with permissions either.

As for the request for 2.8 do you have an open issue for me to mention in the PR?

@xabbuh
Copy link
Member

xabbuh commented Dec 30, 2015

@hboomsma I think you can refer to the same issue (it's also talking about the (not)-atomic behaviour).

@hboomsma
Copy link
Author

@xabbuh #17184 for atomic behaviour in 2.8

@linaori
Copy link
Contributor

linaori commented Dec 30, 2015

Looks like the failure is unrelated to the changes in this PR.

$tmpFile = $this->tempnam($dir, basename($filename));

if (false === @file_put_contents($tmpFile, $content)) {
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
}

// Ignore for filesystems that do not support umask
@chmod($tempFile, 0666 & ~umask());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this done twice? And what does $tempFile refer to?

@hboomsma
Copy link
Author

hboomsma commented Jan 4, 2016

@xabbuh @cs278 @iltar Updated with changes done in 2.3 and merged upward for atomic behaviour

$tmpFile = $this->tempnam($dir, basename($filename));

if (false === @file_put_contents($tmpFile, $content)) {
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
}

// Ignore for filesystems that do not support umask
@chmod($tmpFile, 0666 & ~umask());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking umask() into account here looks like a new feature to me.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xabbuh, I agree you could see it that way, lets not take the umask into account and create a separate pull request for it.

@hboomsma
Copy link
Author

hboomsma commented Jan 4, 2016

@xabbuh updated PR to not take the umask into account.

@@ -1070,13 +1070,19 @@ public function testDumpFile()
{
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';

// skip mode check on Windows
if ('\\' !== DIRECTORY_SEPARATOR) {
$oldMask = umask(0002);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit-test can be simplified now, no need to set the umask anymore.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to explicitly show that the umask does not influence the resulting access permissions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we wanted to improve the tests this way, we should do that on the 2.3 branch imo.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, removed the extra tests, because I will create a separate pull request for enhancing the test and taking the umask into account for 2.3.

@hboomsma
Copy link
Author

hboomsma commented Jan 6, 2016

@xabbuh updated pr to not enhance the unit tests, I will create a separate PR for taking the umask into account with the extra tests for 2.3 after this PR is finished.

@xabbuh
Copy link
Member

xabbuh commented Jan 7, 2016

👍

Status: Reviewed

@fabpot
Copy link
Member

fabpot commented Jan 7, 2016

Thank you @hboomsma.

@fabpot fabpot merged commit 53d6d4b into symfony:3.0 Jan 7, 2016
fabpot added a commit that referenced this pull request Jan 7, 2016
…rmissions (Hidde Boomsma)

This PR was merged into the 3.0 branch.

Discussion
----------

bug #14246 [Filesystem] dumpFile() negates default file permissions

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #14246
| License       | MIT
| Doc PR        | none

Remain BC compatible with Symfony 2.8.
Without this change a chmod is needed after calling `dumpFile`, making it non atomic.

Commits
-------

53d6d4b bug #14246 [Filesystem] dumpFile() negates default file permissions
@fabpot fabpot mentioned this pull request Feb 3, 2016
fabpot added a commit that referenced this pull request Sep 14, 2016
…e (leofeyer)

This PR was merged into the 3.1 branch.

Discussion
----------

[Filesystem] Consider the umask setting when dumping a file

| Q             | A
| ------------- | ---
| Branch?       | 3.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #14246 , #17063
| License       | MIT
| Doc PR        | -

`Filesystem::dumpFile()` does not consider the umask setting and thus creates files with write permissions for everyone (`0666`). Other `chmod()` calls in Symfony do consider the umask setting (see e.g. [here](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/File/File.php#L101) or [here](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/File/UploadedFile.php#L230)), therefore I have adjusted the `dumpFile()` method accordingly.

Commits
-------

fdd266f Consider the umask setting when dumping a file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants