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...)
Contents
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 gamby.mov -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:
- Your filesystem has to support ACLs
- The filesystem must be mounted with ACLs enabled
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.
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
Remount the filesystem for the change to take effect
mount -o remount /home
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.
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
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
OWNERUSER=utena OTHERUSER=apache
apache is getting access to utena's junk
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
You can sanity-check this with getfacl
utena@shimako:~/public_html$ getfacl . # file: . # owner: utena # group: utena user::rwx user:apache:rwx user:utena:rwx group::r-x mask::rwx other::r-x default:user::rwx default:user:apache:rwx default:user:utena:rwx default:group::r-x default:mask::rwx default:other::r-x
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
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 gamby.mov -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.
- 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.
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.
Resources
mount manpage, ACLs are touched upon in the "ext2" subsection
setfacl manpage
getfacl manpage
Author
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.
