Finder: Inherited ACL Duplication

Originator:brunerd
Number:rdar://9160099 Date Originated:20-Mar-2011 12:37 PM
Status:Duplicate/8729952 Resolved:
Product:OS X Product Version:10.6.7/10J869
Classification:Serious Bug Reproducible:Always
 
20-Mar-2011 12:37 PM Joel Bruner:
Finder Inherited ACL Duplication

Summary:
ACLs are redundantly duplicated in copy operations via Finder (but not cp -p in Terminal)

Steps to Reproduce:
On a fresh server install, nothing special, just AFP service running... 
1. Create a folder and make it an AFP share point (turn off Spotlight indexing for one less ACL in the mix)
2. Add a user to the folder ACL (a local, OD, or AD, doesn't matter), in this test case, Admin (501), the defaults permissions are fine (Read Only, Inheritance on)
3. Save and apply rights to folder
4. Create a test document  in TextEdit (on the server to eliminate OS X Client from the ACL equation) and save to folder created in step 1, you could also just touch a new filename too.
5. Duplicate the file in Finder, duplicate the duplicate, etc...
6. Examine the folder with ls -le, the original file will have no ACL, the duplicate will have ACLs applied, duplicates will start to have ACLs repeating/duplicating and "stacking up"
7. When the ACLs gets long enough (esp. on an app) Finder will crash when copying

Expected Results:
ACL methods are aware of an existing duplicate ACEs and do not append new ACEs to the ACL

Actual Results:
ACLs are duplicated and appended until Finder is unable to work with the file (Copy, get Info) without crashing

Regression:
10.6, 10.6.2, bug not present, results were consistent and as expected. 
Example permissions from the test file when duplicated in 10.6 or 10.6.2:
0: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity

10.6.3 (and into 10.6.4) introduced the behavior of adding a Write ACE to the duplication of a file that only had a Read ACE on it, example output:

1st duplication (of file with no ACL):
0: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity

2nd copy (of file above):
0: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
1: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity

3rd, 4th copy, etc… did not duplicate past these two ACEs, why write rights were included is a mystery, it's as if the compliment from the Unix permissions were added because administrator is doing the copying on this file? Bizarre. 

Also Finder starts listing _3_ ACEs on a file that ls -le only lists with _2_, Finder saying this ghost ACE is "Custom".

10.6.5 introduced a new level of duplication, now not only was an errant Write ACE being added to a Read only ACE, but now those entries were being duplicated as well.
Example:
-rw-r--r--@ 1 administrator  admin  4 Mar 18 17:19 test copy 2.txt
 0: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 1: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 2: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity

-rw-r--r--@ 1 administrator  admin  4 Mar 18 17:19 test copy 3.txt
 0: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 1: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 2: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 3: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 4: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity

-rw-r--r--@ 1 administrator  admin  4 Mar 18 17:19 test copy 4.txt
 0: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 1: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 2: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 3: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 4: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 5: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 6: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity

10.6.6 continued this behavior, which becomes fatal for Finder when copying/duplicating packages and Applicaion bundles in a folder with and ACL, Finder will become overwhelmed with the length of the ACL by the 3rd copy and fail, resulting in a truncated application or package and error -41. See the movie called "10.6.6 ACL Chess.app.mov", even one duplication in a folder with one ACL results in a file in the Chess.app have 12 ACEs!

10.6.6 does not address or change the duplication behavior introduced in 10.6.5, or the errant addition of Write rights to what should be a Read ACE introduced in 10.6.3

When "cp -p" is used to copy the errant ACEs are purged and properly reflect the ACL of the parent folder. Seems to be Finder's problem.

21-Mar-2011 11:47 AM Joel Bruner:
Further regression testing notes, AFP need not be involved, and client will behave the same as well when inheritance is turned on  (file_inherit,directory_inherit), just make the folder, apply an ACL with chmod, and Finder will duplicate ACEs without proper checking and duplicates will occur to the point of Finder error -41 on applications and packages.

While this bug affects both client and server, only server makes it easily possible by turning inheritance on by default when using the Server Admin AFP panel, whereas Finder does not turn on inheritance in it's ACLs that are added by Finder

Create a new folder in the root (to avoid any other possible ACL permissions, permission interactions), logged in as administrator (501) - you can also be logged in as anyone else who has write permissions to the folder.

Apply the folder ACLs (the same that server Server Manager would apply with inheritance on) using chmod:
1. mkdir ~/chmodACLTest
2. chmod +a "administrator allow list,search,readattr,readextattr,readsecurity,file_inherit,directory_inherit"  ~/chmodACLTest
3. Copy an application like Chess.app into the folder with Finder, duplicate/copy and recopy the copy, the 3rd duplicate will fail with Error -41 because ACLs are stacking up.
# for a simple file experiment
4. touch ~/chmodACLTest/test 
5. Go to Finder and duplicate the test file and its duplicates.
Inspect permissions in Finder and in addition to Read, the erroneous Write ACE is labeled Custom in Finder.

Inspect with Terminal:

$ ls -led ~/chmodACLTest
drwxr-xr-x+ 6 administrator  admin  204 Mar 21 10:29 chmodACLTest
 0: user:administrator allow list,search,readattr,readextattr,readsecurity,file_inherit,directory_inherit
 1: user:_spotlight inherited allow list,search,file_inherit,directory_inherit

$ ls -le
total 0
-rw-r--r--+ 1 administrator  admin  0 Mar 21 10:28 test
 0: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
-rw-r--r--+ 1 administrator  admin  0 Mar 21 10:28 test copy
 0: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 1: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 2: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
-rw-r--r--+ 1 administrator  admin  0 Mar 21 10:28 test copy 2
 0: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 1: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 2: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 3: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 4: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
-rw-r--r--+ 1 administrator  admin  0 Mar 21 10:28 test copy 3
 0: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 1: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 2: user:administrator inherited allow write,delete,append,writeattr,writeextattr,chown
 3: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 4: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 5: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 6: user:administrator inherited allow read,execute,readattr,readextattr,readsecurity
 7: user:_spotlight inherited allow read,execute

Notes on Admin's ACL being Read Only vs. Unix permissions:
You can also give admin write permissions in the ACL and the same behavior will occur, while it seems like a poor example to have the same user duplicating the file having Read Only in the ACL, it should and is possible, because the Unix permissions allow this, what the example highlights is that a Write ACE is inexplicably written when that is not supposed to be inherited from the parent folder.

Comments

10.6.8 update

...does not appear to fix this, at least entirely. I've been unable to generate a Error -41 with some very quick cursory tests, but the Finder continues to make superfluous explicit copies of inherited ACLs.

By joe.carroll at June 27, 2011, 10 p.m. (reply...)

ACL bug, root cause

I don't know whether to laugh or cry... I used to maintain the ACL code in the Mac OS X kernel. This is a user-space bug in the DesktopServices framework.

Although this is not usually a problem, since only foolish/untrained administrators use Finder copies on systems being used as servers, I tried several times to get the Desktop Services folks to fix this. Mac OS X has multiple "copy engines", and the one in libc gets this right, while the one in the DesktopServices framework gets this wrong.

The problem is that the finder "copy engine" code sets an ACL in the openx_np() system call, rather than using the chmodx_np() system call after the fact to set an explicit ACL. The ACL it passes to openx_np() is obtained from the source file system object via getattrlist() (but could as easily have come from statx_np()). So the ACL being set is the combination of the ACL set explicitly by the openx_np(), and the ACL being set as a result of the inheritance bit on the container directory in which the new file or directory is being created.

This is in fact necessary, since the only way to make image backups of a subtree such that the copied subtree has exactly the same permissions in the target subtree as it had in the source subtree is to set all of the ACLs that were on the source object onto the target. Anything else loses permissions grants or denials on the copy of the object which were present on the original. This is either inconvenient, in the case of grants, or a critical security bug, in the case of denials.

You can also see where this would be a necessary step for a backup/restore operation, where the date is serialized into an archive format on the backup, and deserialized back into the file system on a restore, which could be a partial archive restore.

Things can get even more complicated when Time Machine and Spotlight are thrown into the mix, since Spotlight adds inherited ACEs to permit it to index directory contents that would otherwise be denied it by ACL, as does Time Machine (for some reason, they do not share a common group ID and utilize a single shared system functionality ACE, but I digress...). Likewise Time Machine sets an inherited ACE on its backup volume, for similar reasons.

The correct fix is to do ACE deduplication in the case that the target directory container has inherited ACE entries which match the ACE entries on the source object, and remove duplicates from those explicitly listed in the openx_np() call. The alternative approach is to explicitly set exactly the desired ACL on the target after the target is created -- this has the drawback that you would need to explicitly know the container ACLs inherited ACE list in order to aggregate it yourself, but has the advantage that you won't be denied access to the object during creation if your openx_np() ACL contains explicit rights grants for the group or user that the creating entity runs under (this should be coupled with a subsequent "deny everyone" ACE to avoid a security race, which makes this the less desirable workable solution).

Note that the above should make it obvious why a depth-first post-application of ACLs on copied objects wouldn't work; apart from the security problems in the order of operation window, network protocols such as AFP and NFSv$ and SMB all use connection credentials rather than request credentials (NFSv3 uses request credentials), and even privileged users do not have access to other users keychains or session passwords in effect for a given copy operation.

By lambert.tr at March 25, 2011, 8:14 a.m. (reply...)

Thanks!

Well, I think that darn near definitively nails it down, thanks! BTW, the ACL error would happen via AFP as well as local copies on the server, in my environment the server and client is Active Directory bound, simply copying a PKG package the you have R/W access to in the ACL results in this duplication, no foolish/untrained admin needed, just a simple copying by an end-user!

The lack of trust in Finder's abilities by a former Apple employee is pretty funny, the laugh/cry kind! The one and only GUI file manager you are given by Apple in OS X should not be trusted?! We might know this to be true from experience and gut feeling, but should the average user have this level of distrust? I don't think they should...

--

So the bug's been merged with an existing one and Apple Engineering has acknowledged it... Snow Leo Font Update came out the other day for the 10.6.7 OTF bug, which goes to show, they want to put off 10.6.8 for as long as possible, because if it ever comes out, it'll be the last core OS update!

Causing problems in the wild

I've bumped into this recently, where some deeply nested files on a customer's fileshare that contains their working files had as many as 57 ACLs and these had started causing Time Machine backups to fail.

By joe.carroll at March 23, 2011, 10:22 a.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!