Taking advantage of filesystem ACLs

On most servers, dynamic website code such as PHP is run as the apache user (we're assuming a very common setup with the Apache webserver, and mod_php). This is because the PHP interpreter is embedded in apache itself (thanks to mod_php), which is an easy way to provide good performance. Security issues aside, of which there are many, this tends to cause problems when the application code needs to access or write files to a directory owned by a user.

Thankfully, we have a vastly better alternative to setting mode 777 on all our precious datas (that's so last century, dahling...)

The problem

Let's have a look at a typical user's public_html directory, we're assuming that you're familiar with standard ls output

utena@shimako:~/public_html$ ls -lha
total 649M
drwxr-xr-x 14 utena utena 4.0K 2010-05-19 11:59 .
drwxr-xr-x  7 utena utena 4.0K 2010-05-19 11:58 ..
-rw-r--r--  1 utena utena  76M 2007-03-30 21:06 Colorful_Orchestra.mpg
-rw-r--r--  1 utena utena 288K 2007-02-17 16:12 EMS USB Joypad2 (ver2.7).exe
-rw-r--r--  1 utena utena 323M 2009-08-10 00:26
-rw-r--r--  1 utena utena 121M 2006-05-15 01:00 [iichan]_Maid_in_Akihabara_Episode_5.avi
-rw-r--r--  1 utena utena 2.5M 2007-04-25 17:51 [iitran]Emma_Promo[748845E6].avi
drwxr-xr-x 13 utena utena 4.0K 2009-06-21 02:49 images
drwxr-xr-x  2 utena utena 4.0K 2006-12-29 22:42 LaC_pasta
drwxr-xr-x  2 utena utena 4.0K 2009-06-21 03:02 Tsukimiya_Ayu_no_Taikutsu
-rw-r--r--  1 utena utena 1.2K 2010-07-08 22:25 upload_handler.php
drwxr-xr-x  2 utena utena 4.0K 2007-02-23 14:22 Wind_-_Rustle_CD

Let's assume that upload_handler.php will accept images from a user, resize them, then store them in the images/ directory. upload_handler.php will be run by apache, as the apache user. But the apache user doesn't have write permissions on the images/ directory, so it won't succeed.

As you can see, the files and directories are owned by utena. utena has read-write access to everything, denoted by 'rw' or 'rwx' in the left-most column of permission bits. apache isn't a member of the utena group, so it falls back to using the 'other' permissions, which are read-only, seen in the right-most column of permission bits.

A poor solution

Let's face it, uploading files is a pretty useful thing to do, especially if you have any sort of social community, or run a blog with a nice builtin text editor, etc.

Most software suggests the "nuclear" option: let everyone have write-access to your files. This is okay if you're the only user on the server, but very bad if there are other users with access to the server. That's definitely the case on most shared hosting servers.

Even if you have your own server, or mostly-trust the other people on the server, it's just an ugly solution. To add annoyance, uploaded files will be owned by the apache user, instead of you. This sometimes makes it a problem to delete or rename them.

A better solution

This is where filesystem ACLs come in. As always, it's good if you spend some time reading up on them, but it's easy to get started with ACLs very quickly.

A couple of quick points to note. ACLs are a filesystem features, which means:

ext3, the most common filesystem in use on linux today, supports ACLs just fine. To make use of ACLs, it's best to update your fstab to include them.

Enabling ACLs

This requires root privileges. All of Anchor's shared-hosting servers have ACLs enabled by default. If you have a dedicated server, ACLs can be enabled with no downtime, which is great news.

  1. The first step involves editing your /etc/fstab - you do understand what you're doing, right?

    # add "acl" to the list of mount options, like so:
    # <file system>            <mount point>   <type>  <options>     <dump>  <pass>
    /dev/mapper/shimako-home   /home           ext3    defaults,acl  0       2
  2. Remount the filesystem for the change to take effect

    mount -o remount /home
  3. You can confirm that the change has taken effect by inspecting the output of the mount command

    /dev/mapper/shimako-home on /home type ext3 (rw,acl)

Setting the ACLs

You use the setfacl command to do this, it rocks.

  1. Determine the target directory and cd there. Let's assume that I want apache to have full access to my public_html directory. It's best to restrict this futher if you can, eg. ~/public_html/uploads/

    cd /home/utena/public_html
  2. Set the usernames you'll be using. OWNERNAME is the your own username, OTHERUSER is the one that's getting this extra access. In this case, OTHERUSER is apache


    apache is getting access to utena's junk

  3. Add the ACL entries. Note that we add specific entries for the named owner user as well (utena). This is because $OTHERUSER may now create files there, and you need the privileges to be equal

    setfacl -R -m   u:${OWNERUSER}:rwX .
    setfacl -R -m d:u:${OWNERUSER}:rwX .
    setfacl -R -m   u:${OTHERUSER}:rwX .
    setfacl -R -m d:u:${OTHERUSER}:rwX .

    This means that both utena and apache have read-write access to all files and directories. In addition, any files or directories created later will also get the right permissions

  4. You can sanity-check this with getfacl

    utena@shimako:~/public_html$ getfacl .
    # file: .
    # owner: utena
    # group: utena

    You should read the manpage for setfacl if you need to understand this better, but it's generally clear that the permissions are appropriate for what we need now

  5. A tip for the curious: you might well wonder how this affects the old "user:group:other" permissions that you're familiar with. They're not gone, but the filesystem now maps the ACLs to something roughly appropriate when you run ls. Let's have a look:

    utena@shimako:~/public_html$ ls -lha
    total 649M
    drwxrwxr-x+ 14 utena utena 4.0K 2010-07-08 23:03 .
    drwxr-xr-x   7 utena utena 4.0K 2010-07-08 22:42 ..
    -rw-rw-r--+  1 utena utena  76M 2007-03-30 21:06 Colorful_Orchestra.mpg
    -rw-rw-r--+  1 utena utena 288K 2007-02-17 16:12 EMS USB Joypad2 (ver2.7).exe
    -rw-rw-r--+  1 utena utena 323M 2009-08-10 00:26
    -rw-rw-r--+  1 utena utena 121M 2006-05-15 01:00 [iichan]_Maid_in_Akihabara_Episode_5.avi
    -rw-rw-r--+  1 utena utena 2.5M 2007-04-25 17:51 [iitran]Emma_Promo[748845E6].avi
    drwxrwxr-x+ 13 utena utena 4.0K 2009-06-21 02:49 images
    drwxrwxr-x+  2 utena utena 4.0K 2006-12-29 22:42 LaC_pasta
    drwxrwxr-x+  2 utena utena 4.0K 2009-06-21 03:02 Tsukimiya_Ayu_no_Taikutsu
    -rw-rw-r--+  1 utena utena 1.2K 2010-07-08 22:25 upload_handler.php
    drwxrwxr-x+  2 utena utena 4.0K 2007-02-23 14:22 Wind_-_Rustle_CD

    You'll notice that there's now a plus-sign (+) at the end of each row of permissions bits. This is your indication that ACLs are in use, and that you'll need to use getfacl to determine exactly who has access. If you compare the rwx bits now, you'll notice that the 'group' now has write permissions. The filesystem layer has a mechanism to figure out what approximation to show you, but you shouldn't rely on it too much. getfacl will tell you everything you need to know.

  6. Go ahead and upload some files, it should Just Work, without doing nasty things like giving the whole world write-access on your files. Similarly, as the real owner of those files, you'll be able to move, delete and mangle as though they were your very own.
  7. If anything doesn't seem right, the mask entry may need tuning (though that's not the only explanation for possible problems). You should really read the setfacl manpage at this point :)

Can we do better than this?

Must we run our PHP code as the apache user? In short, no, it's not a necessity.

On shared hosting servers, Anchor uses a mechanism called "suexec" to run code as the user that owns it. suexec deserves an article all of its own, but to sum it up, it's a big win because it completely sidesteps all the problems we've discussed earlier.



Barney Desmond is a Linux systems administrator at Anchor with a passion for free software and open source solutions. Anchor is a provider of Australian web hosting and dedicated servers.

Wiki: dedicated/Taking_advantage_of_filesystem_ACLs (last edited 2010-07-08 23:31:17 by BarneyDesmond)