Posted by mjorlitzky on January 25, 2013 at 6:11pm
14 followers
| Project: | Drupal core |
| Version: | 8.x-dev |
| Component: | file system |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs work |
| Issue tags: | needs backport to D7, Needs manual testing |
Issue Summary
Right now Drupal is unusable with filesystem (POSIX) ACLs. It's been broken for years. This was previously #944582: ./sites/default/files directory permission check is incorrect during install AND status report and #1333390: file_prepare_directory() / is_writable() on Linux don't support ACLs which are/were doomed to failure.
Guidelines to reproduce:
- build a clean Drupal 8 development environment
- In sites/default,
- chown -R nobody files
- chmod -R 700 files
- setfacl -R -m user:apache:rwx files/
- setfacl -Rd -m user:apache:rwx files/
- Install Drupal 8
- Add a new Article (uploading an image should fail).
Notes:
- change apache in step 2. for the username of your httpd server.
- step 4. needs to be confirmed or an alternative method proposed.
| Attachment | Size | Status | Test result | Operations |
|---|---|---|---|---|
| drupal-writable-executable-fix-7.19.patch | 5.69 KB | Idle | PASSED: [[SimpleTest]]: [MySQL] 39,751 pass(es). | View details | Re-test |
Comments
#1
Thanks @mjorlitzky, at a glance this looks pretty good. This needs to be fixed in 8.x first then backported to 7.x per the backport policy.
The 8.x patch from #944582-56: ./sites/default/files directory permission check is incorrect during install AND status report will need to be rerolled against 8.x minus the installer changes.
Instructions for rerolling patches.
#2
Tagging, this would still need a forward port/reroll to apply to 8.x.
#3
i will reroll this patch against 8.x
#4
We worked on this in the Drupal Spring London with Pasive and joates. We basically took the patch provided for D7 in this issue summary and ported it to D8 up to date. Thanks to Joates to guide us through the process!
#5
Code looks great!
#6
Many things look wrong in there.
First, the original post mentions that Drupal is broken when ACLs are in use, but doesn't mention why checking the execute bit (which has nothing to do with ACLs) would fix anything. Other then parsing the ACLs manually, the only way to check if you can write a file in a given directory is to try to write it, and that's what #1333390: file_prepare_directory() / is_writable() on Linux don't support ACLs actually tried to do.
Second, using
drupal_realpath()without checking the return value is *really wrong*. Remote stream wrappers do not implement->realpath(), so this is going to return FALSE.Third, I don't see at all why this is necessary, because both
is_executable()andis_writable()are basically wrappers aroundstat()and as a consequence they *actually work* with stream wrappers (as long as they implement->stat()).Finally, I doubt
is_executable()on a directory returns what you expect it to return on Windows.#7
ty for the feedback.
possible alternative to drupal_realpath() (deprecated) is discussed here..
#1201024: drupal_realpath() should describe when it should be used
[edit] in the case of a remote resource ... [/edit]
returning FALSE is certainly not useful, should probably at least test for this & log an error when it occurs.
#8
Hi Damien and Joates. Thank you guys for the feedback. As far as I can tell at this point this issue should have never existed? Would you suggest another alterantive or we'll just rely on the fact that drupal does not support ACLs full stop.
Please let me know as I'm new at drupal issues so sincerely I don't know how to proceed from here.
Cheers!
Juan B
#9
From reading Damien's response, I think the first thing to do here is to provide detailed, reproducable steps on how to get Drupal to fail when it should work.
#10
Steps to reproduce in drupal-7.20 (swap apache with your website user):
IMCE will fail, claiming that the directory (sites/default/files) is not writable. This is due to
file_prepare_directory('public://', FILE_CREATE_DIRECTORY)failing, and is fixed by the patch which modifiesfile_prepare_directory().#11
Thanks, I'll try this on D8 and get back with the results here.
#12
in response to #10 Posted by mjorlitzky..
it would be more constructive if we can all agree that this is an 8.x issue now,
there is no 8.x release of IMCE
Notes:
[edit]
// 28-Feb-2013
Modified the instructions to implement full excluded file access to the entire files/ sub-tree (user = nobody)
and added recursive ACL permissions as Drupal needs to store file uploads in several sub-folder locations.
[/edit]
#13
You don't really need IMCE to reproduce the issue in 8.x (if it exists). Just call
file_prepare_directory('public://', FILE_CREATE_DIRECTORY)somewhere and see if it works. IMCE is just the reason why this is a complete show-stopper for us.#14
Ok, I see what's happening. PHP has a special case for local files in which it uses access(2) or the equivalent Windows call. This supports ACLs. If called on a stream-wrapper, it defaults to a (very complicated) process based on the stat(2) structure returned by the stream-wrapper implementation.
More precisely it checks part of the
.modestructure depending on:getuid(2)) is the same as the.uidin the stat, it uses the "user" part of the mode;getgid(2)) or the supplementary groups (as returned bygetgroups(2)is the same as the.gidin the stat, it uses the "group" part of the mode;So, one way of moving forward here, would be to modify the stat implementation in our local streamwrapper to fake the mode by calling
is_readable(),is_writable()andis_executable()manually, and return the proper structure.#15
Is this related to #1908440: CM permission settings by FileStorage make commandline tools like drush unusable.?
#16
Re #14: thanks Damien for locating what seems to be the root cause of this..
from core/lib/Drupal/Core/StreamWrapper/LocalStream.php, line 472
<?phppublic function url_stat($uri, $flags) {
$this->uri = $uri;
$path = $this->getLocalPath();
// Suppress warnings if requested or if the file or directory does not
// exist. This is consistent with PHP's plain filesystem stream wrapper.
if ($flags & STREAM_URL_STAT_QUIET || !file_exists($path)) {
return @stat($path);
}
else {
return stat($path);
}
}
?>
#17
in response to #9 and #12..
after setting
chmod 700 filesyou can clearly see from the terminal that my normal user (joates) is group member but cannot gain access.
getfacl shows the ACL permissions (as described in #12)
(screenshot attachment not working?)
on a fresh install of D8 using default configuration (public:// streamwrapper) i am able to upload an image without error.
#18
try again with the screenshot..
link: http://i.imgur.com/G0s2i99.png
afterwards i realised that having www-data as the directory owner is not too helpful :-p
so i did a
chown -R joates:joates filescleared cache and tried again to upload the image, and it did indeed FAIL to upload the file(which sort of feels like causing it to fail when it *should* fail, but maybe i don't understand ACLs correctly --
does?)setfaclin the top folder apply to every childUpdate: even with recursive ACL the file upload still fails.
link: http://i.imgur.com/FesrnJV.png
#19
can someone with superior ACL sysadmin skills to me please confirm that it seems that Drupal is not providing support for ACLs ?
(perhaps due to the situation Damien describes in #14)
and maybe change the title of this issue if that is the case :)
#20
@joates - Thanks for all your work on this issue. Could you please update the issue summary with the steps to reproduce, that way others can update them too and you don't have to keep editing your comments :)
#21
ok
#22
The current steps to reproduce probably won't work I'm afraid. Uploading files—in and of itself—has always worked. The filesystem ACLs do really allow you to write the file, so if you try to do it, it will work.
The problem is when Drupal does its heuristic to determine, "will I be able to write this file if the user tries to do it?" That test is currently broken, so the answer is "no" even though it should be "yes" (thanks to the ACL).
#23
Updated patch for 7.22.
#24
The last submitted patch, drupal-writable-executable-fix-7.22.patch, failed testing.