Articles May 6, 2005 at 8:58 am

Grokking Darwin ACLs

I have to admit, when I first heard that Apple was adding ACLs to the next version of OS X, I got a pretty nasty lump in my throat and ordered another pint of ale. I was first introduced to ACLs in DFS on AIX and I still have nightmares and flashbacks of files which can’t be deleted by root and will forever remain on the disk until the next newfs. After reading through Apple’s new File Services manual however, I’ve learned to stop fearing and start loving the ACL. Apple’s implementation of ACLs on Darwin is actually very intuitive and makes a whole lot of sense.

Getting started

So – what’s an ACL? An Access Control List is a set of rules that either allow or deny the privileges of performing various actions (read, write, execute, etc) to a user or group on a filesystem object such as a file or a directory. Like normal permissions, they can be inherited from parent to child and unlike normal permissions, they aren’t limited to the old familiar User, Group, and Other ownership-based permissions. Filesystem objects in Tiger still retain User, Group, and Other UNIX permissions – ACLs either work with or against these permissions. Let’s look at an example:

neo:/Users misha$ ls -le
drwxrwxr-x +   2 misha  misha    68 May  5 19:58 MyDirectory
 0: user:weebl allow list,add_file
 1: user:bob allow list,add_file

As you can see, the e flag for ls displays ACL information. ls in normal -la mode will show a plus sign next to the UNIX permissions for any files which have an ACL whether there are any ACL entries or not. Adding the e flag will show us the ACL entries directly following the filesystem object whose ACL they belong to. In this example, the directory “MyDirectory” is owned by the user misha and the group misha and they’ve both been granted rwx permissions. In addition to that, the users weebl and bob have been granted permission to add files to MyDirectory and to list its contents.

The Finder (God love it) was never a very good tool for modifying permissions on OS X and with ACLs, it’s actually pretty unusable. UNIX admins will be glad to know that although you can use Workgroup Manager to change ACLs in Tiger Server, the chmod command has been updated as the weapon of choice in our war against the users. Along with the freshened ls command, adding, removing, and modifying ACLs is almost as easy as working with UNIX perms. The man page for chmod is a gold mine of information, complete with examples.

Before you go wild and starting chmoding everything in sight like I tried to after my first Tiger install, there are a couple of things to note. First off, Darwin ACLs only work with the HFS+ (extended) filesystem and secondly, a filesystem must be prepped with the fsaclctl command:

neo:/Users misha$ sudo fsaclctl -p /Volumes/panther
Access control lists are not supported or currently disabled on /Volumes/panther.
neo:/Users misha$ sudo fsaclctl -p /Volumes/panther -e
neo:/Users misha$ sudo fsaclctl -p /Volumes/panther
Access control lists are supported on /Volumes/panther.

Ed. Note: With fsaclctl you are more than welcome to use ACLs on OS X client, although I’m not sure of the usefullness of this on a client system. Also keep in mind that ACLs are extended attributes associated with the files themselves. So setting an ACL on Firewire drive means the ACLs will be there when you plug that drive into another system.

Whew. If you do happen to lock root out of a file, you can just turn off ACLs with fsaclctl, rm the file, and be back on your feet without a newfs – er diskutil reformat.

Adding entries to an ACL

An ACL entry has three components – the user or group that the rule pertains to, whether it’s an “allow” or “deny” rule, and the permissions that the rule either grants or revokes. The first two components are self-explanatory, but there are a couple of caveats. First off, you cannot specify whether the entity the ACL entry pertains to is a user or a group. This means that you should be wary of having a user and a group with the same name. If you do have a user and a group with the same name, chmod picks the user as the entity. The second thing to be wary of is that access is determined by the first matching ACL entry in the list – by default the list is ordered user-deny, user-allow, group-deny, group-allow to avoid confusion, but the order can be modified with certain flags to chmod.

Ed. Note: Each entry in an ACL is called an Access Control Entity, or ACE. Each ACL contains a minimum of one ACE.

There are seventeen (ACK!) permissions which can be granted or revoked in an ACL entry. Workgroup Manager has a slightly different list which only contains thirteen. The chmod man page has detailed information about each permission. Here’s a simple listing of them.

The following permissions are available for all filesystem objects:

  • delete
  • readattr
  • writeattr
  • readextattr
  • writeextattr
  • readsecurity
  • writesecurity
  • chown

The following permissions are available for directories:

  • list
  • search
  • add_file
  • add_subdirectory
  • delete_child

The following permissions are available for files, links, devices, etc:

  • read
  • write
  • append
  • execute

In addition to the permissions, ACL inheritance is specified in the third part of the ACL entry by the following keywords:

  • file_inherit
  • directory_inherit
  • limit_inherit
  • only_inherit

The first two keywords are self-explanatory and probably what you want to use in most cases. limit_inherit only allows ACL entries to inherit to immediate subdirectories of the directory containing the ACL entry and only_inherit allows you to create entries that don’t effect the directory whose ACL they belong to but do effect its children. It’s worth noting that no inheritance is the default for an ACL entry.

That said, a simple ACL entry allowing bob to read files in a directory which will be inherited looks like this:

bob allow list,directory_inherit,file_inherit

The chmod command uses the +a flag to add an entry to an ACL. Here’s an example of how to use this entry:

neo:~/MyDirectory misha$ mkdir Dir1
neo:~/MyDirectory misha$ chmod +a "bob allow list,directory_inherit,file_inherit" Dir1
neo:~/MyDirectory misha$ ls -lea
total 0
drwxrwxr-x     3 misha  misha   102 May  5 21:16 .
drwxr-xr-x + 125 misha  misha  4250 May  5 21:16 ..
drwxrwxr-x +   2 misha  misha    68 May  5 21:16 Dir1
 0: user:bob allow list,file_inherit,directory_inherit
neo:~/MyDirectory misha$ mkdir Dir1/Dir2
neo:~/MyDirectory misha$ ls -lea Dir1
total 0
drwxrwxr-x + 3 misha  misha  102 May  5 21:16 .
 0: user:bob allow list,file_inherit,directory_inherit
drwxrwxr-x   3 misha  misha  102 May  5 21:16 ..
drwxrwxr-x + 2 misha  misha   68 May  5 21:16 Dir2
 0: user:bob inherited allow list,file_inherit,directory_inherit

To delete the ACL entry, simply use -a:

chmod -a "bob allow list,directory_inherit,file_inherit" Dir1

ACL entries can also be deleted by number:

chmod -a# 0 Dir1

When ACLs are inherited from directories to files, some funny things happen. ACL entries are translated a bit – for example, list becomes read. Consider:

neo:~/MyDirectory misha$ chmod +a "bob allow delete,chown,list,search,add_file,add_subdirectory,delete_child,file_inherit,directory_inherit" Dir1
neo:~/MyDirectory misha$ touch Dir1/File1 
neo:~/MyDirectory misha$ ls -lea Dir1
total 0
drwxrwxr-x + 3 misha  misha  102 May  5 21:25 .
 0: user:bob allow list,add_file,search,delete,add_subdirectory,delete_child,chown,file_inherit,directory_inherit
drwxrwxr-x   3 misha  misha  102 May  5 21:16 ..
-rw-rw-r-- + 1 misha  misha    0 May  5 21:25 File1
 0: user:bob inherited allow read,write,execute,delete,append,chown

This is expected behaviour. It’s also worth noting that the output of ls -lea can be a bit misleading. Sometimes the ACLs show up, sometimes they don’t. Witness:

neo:~ misha$ mkdir MyDirectory
neo:~ misha$ chmod +a "bob allow list,directory_inherit" MyDirectory 
neo:~ misha$ mkdir MyDirectory/Dir1
neo:~ misha$ ls -lea MyDirectory    
total 0
drwxrwxr-x +   3 misha  misha   102 May  5 21:35 .
drwxr-xr-x   125 misha  misha  4250 May  5 21:35 ..
drwxrwxr-x     2 misha  misha    68 May  5 21:35 Dir1


neo:~ misha$ ls -lea MyDirectory/Dir1
total 0
drwxrwxr-x + 2 misha  misha   68 May  5 21:35 .
 0: user:bob inherited allow list,directory_inherit
drwxrwxr-x + 3 misha  misha  102 May  5 21:35 ..
 0: user:bob allow list,directory_inherit

Ah. Wierd.


With seventeen different ACL permissions, UNIX permissions, users, groups, others, and of course “Locked files,” things can get a little silly when you’re trying to let The Boss read everyone else’s files without letting him delete your filesystem by accident. That said, ACLs free the admin to create intelligent user/group mappings that reflect organizational structure, not file structure. Without ACLs, we’re left adding members to groups they don’t belong to just so that they’ll have permission to view files that they need to fill their job function. With ACLs, weebl in sales doesn’t become a member of the engineering group just so he can ready the next press release, weebl is simply given read access to the engineering group’s directory, which they rightly own. This will allow for more intelligent directory service design and simplify system administration, not complicate it. And by extending existing UNIX commands instead of creating new ones, Apple has made it quite simple for us to jump on the bandwagon and utilize this feature set. Thanks!

No Comments

  • The file services manual states: "Only HFS+ provides local file system
    support for ACLs. In addition, only SMB and AFP provide network file
    system support for ACLs in Windows and Apple networks respectively."

    Does this mean that accessing a directory/file via ftp will not be able to be
    controlled by ACL’s?

    Mike S.

    • Actually, that statement of theirs is a little odd. ACL support is at the kernel
      level of the operating system and a quick test shows that they are obeyed
      accessing files over FTP. I’d bet they’re talking about compatibility through
      GUI tools. I quickly tried to get Workgroup Manager to do what I wanted
      ACLs last week but had little success. Here’s a snippet of the user misha
      putting an empty file into a directory that he only has access to via ACLs:

      ftp> put chicken
      local: chicken remote: chicken
      229 Entering Extended Passive Mode (|||49531|)
      150 Opening BINARY mode data connection for 'chicken'.
           0       0.00 KB/s 
      226 Transfer complete.
      ftp> ls -la
      229 Entering Extended Passive Mode (|||49533|)
      150 Opening ASCII mode data connection for '/bin/ls'.
      total 0
      drwxr-xr-x  4 bob    admin  136 May  9 09:21 .
      drwxr-xr-x  3 misha  misha  102 May  9 09:19 ..
      -rw-r-----  1 misha  admin    0 May  9 09:21 chicken
      -rw-rw-r--  1 misha  admin    0 May  9 09:21 file1
      226 Transfer complete.
    • I got the same result: You can set ACL, but if You add files or folders to a Share Points via FTP, osx does NOT apply ACL rules. I wuold like new files will inherit from parent folder, but if a new user add a folder, this folder does NOT inherit extended permission (in my case RW permission for 3 different gropus)

      • From page 20 of the file services admin guide…

        “Supported Volume Formats and Protocols
        Only HFS+ provides local file system support for ACLs. In addition, only SMB and AFP provide network file system support for ACLs in Windows and Apple networks respectively.”

        Breaking my server to save yours.

        Josh Wisenbaker

  • command-shift-+

    I’ll look at upping the css entries.

    Changing the world, one server at a time.

    Joel Rennich

  • Well, I’ve tried my first pass with these ACLs, and I find them not even close to ready for prime time. Main problem (confirmed by Apple support): Removing (or adding) a user from a group does *not* remove that user’s rights as defined in the ACL.
    So, when Jane moves from sales to graphics, and her account is removed from the sales group and added to the graphics group, she still has access to the sales data, and doesn’t have access to the graphics data. The “workaround” is to remove the group, save and re add. Oh, but that doesn’t proagate to children (regardless of the settings, or even using the “propogate permissions” option in WGM’s access tab. This is not real ACLs. I’m no Windows lover, but the NTFS ACLs are now quite good. I’m deciding now if this $20k worth of XServe and RAID is any use to us as a file server.
    Granted, I’m using WorkGroup Manager, not CLI, but I shouldn’t have to drop to a CLI for this. This stuff should be easy.

  • Some notes on things I’ve run into while working on this, I have to agree that
    ACLs aren’t ready for prime time just yet.

    You can set permissions that should be inherited by the child folders/files but
    whether they’re inherited or not seems to depend on if they existed before or
    after the ACL was created. For files/directories copied in after they inherit, if
    they were there already they won’t unless you force the issue in Workgroup
    Manager. (I can find no way to force this from the command line.)

    For example:

    chmod +a "hmslab allow list,file_inherit,directory_inherit" labs-acl

    ls -le

    drwxr-xr-x + 6 nobody nobody 204 Nov 16 10:14 labs-acl
    0: user:hmslab allow list,file_inherit,directory_inherit

    cd labs-acl

    ls -le

    dr-xr-xr-x 4 nobody nobody 136 Nov 10 15:44 Installs
    dr-xr-xr-x 4 nobody nobody 136 Aug 26 16:39 ttl

    Not even a + to show there should be an ACL applied to them. Now if I go
    into Workgroup Manager on the "Access" tab I can chose "Propogate
    Permissions" from the drop down menu at the bottom (below the ACL listing

    ls -le

    dr-xr-xr-x + 4 nobody nobody 136 Nov 10 15:44 Installs
    0: user:hmslab inherited allow list,file_inherit,directory_inherit
    dr-xr-xr-x + 4 nobody nobody 136 Aug 26 16:39 ttl
    0: user:hmslab inherited allow list,file_inherit,directory_inherit

    And that _is_ what I expected to happen to start with, chmod doesn’t seem
    to offer a way to do this, I tried using -R with the +a and it failed.

    Secondly while fiddling with the permissions in Workgroup Manager after
    getting them propogated I found that modifying an existing ACL for a user
    may _not_ result in that modified ACL propogating but new ACLs propogating
    down with the new info. I can’t get this to repeat constantly but the first time
    I had set the same ACL as above (list, dir & file inheritance) and applied it to
    some subdirectories as well since it didn’t propogate. In that case some of the
    subdirectories added the additional ACL permissions as ACL 1, others modified
    the existing ACL 0 (the expected behavior) to match the root ACL. It does
    seem to work correctly as long as you modify _only_ the root ACL and
    propogate the changes. If you want to add a new ACL permission to an
    existing directory hierarchy with varying ACLs you might not get the results
    you were expecting so I’d recommend you try it on a test directory tree first
    to see.

    Something really strange I ran into while testing. I deleted two subdirectories
    and went to copy them back to see if they’d inherit properly. They did, or
    rather what would copy of them did. I got a "Bus Error" shortly into the copy
    and very little copied over. Removing the ACL on the parent directory I was
    able to copy the subdirectories back in fine without any bus errors. I have no
    idea why having an ACL in place would cause a bus error. (And note it didn’t
    fail all the files, just some of them.)

  • Here’s a funny problem I just can’t figure out:

    I have an OS X 10.4.9 file server bound to a windows 2003 Active Directory server. The file server has ACLs enabled. How do I add an ACE to a folder such as granting write access for the default Windows AD group “Domain Users”. It seems like there are problems because this type of group name has a space character between Domain and Users.

    I tried the following command and received the following error:

    chmod +a "Domain Users allow write" foldername
    chmod: Unable to translate Domain to a UID/GID: Invalid argument

    I have no problems creating ACEs when the AD group name has no spaces such as

    chmod +a "mygroupname allow write" foldername

    I’ve also noticed that if I have an AD group with uppercase letters I must lowercase all the letters for the chmod command to work.

    Anyone have any ideas how to do this?
    I have tried

    chmod +a "'MYDOMAINNAME\domain users' allow write" foldername
    chmod +a mydomainname\\domain\ users\ allow\ write foldername

    These problems do not present themselves when I use workgroup manager.

Leave a reply

You must be logged in to post a comment.