Filesystem/Security

Good security is like an onion, it has many layers. The file system is just another layer in the proverbial onion. While there are numerous file systems in existence, this guide tries to remain agnostic and focus more on the hierarchy itself rather then an individual implementation.

Partitioning
Partitioning is a key part of implementing security at the file system level.


 * It limits the impact of disk failure
 * It simplifies the process of creating backups
 * It allows administrators to add restrictions such as quotas and read-only permissions more effectively

File System Hierarchy
To better understand how to divide the file system across partitions and apply various restrictions, we need to understand a little about the function of the file system hierarchy and its major directories. Systems based on GNU/Linux or FreeBSD, like Gentoo, borrow from the traditional Unix file system hierarchy. This hierarchy was designed in a time when many physical disks where needed to span the whole system. In modern times with larger storage mediums being common place, average users need not worry about partitioning and file system hierarchy too much. But on a server we need to have a finer grained control over the system and manipulate it to our will.

Some of the more common directories include:

/       Pronounced as "root", this is the top level of the hierarchy. All other file systems are mounted somewhere below this one.

/root   Is the home directory of the root user. Typically email from daemons such as cron will be sent here.

/boot   Typically holds bootloader and its configuration, as well as kernel binaries.

/etc    On modern systems like GNU/Linux and FreeBSD this holds system wide configuration information and is a good target for regular backups.

/bin    System binaries are located here. Tools like grep, ls, and tar.

/sbin   Essential system binaries are located here; for example things to mount and create file systems. As well as the initialization daemon. Superuser privileged is required to use them.

/lib    System libraries are located here. On most 64bit systems /lib is usually just a symlink and separate /lib32 and /lib64 directories will exist.

/dev    Special device files are located here. This is one of the most important directories as its contents are how Unix-like systems interface with hardware from all but the lowest level, the drivers themselves.

/home   This directory is where the typical home directory for system users go. It usually isn't a good idea to put network shares for user home directories here.

/opt    Is a place for non-default software. A good generalization is that, if the software didn't come from Portage or another Gentoo maintained source, it should probably go here. Also troublesome software that doesn't cleanly follow the Unix File Hierarchy should go here to avoid disturbing the rest of the file system.

/tmp    This is scrap space that is used per-session and is typically overwritten on a reboot.

/var    This directory has been described as "multi-purpose" which is very accurate. It contains items ranging from system logs to PID files to spoolers, it even has its own temporary space.

/var/tmp As you might have guessed, this is the temporary space within /var. It deserves its own listing because Portage uses this as an area to unpack and build distfiles.

/usr    This is often referred to as "a secondary hierarchy" because more then often it mirrors the root directory in its layout, only it is where user applications are stored rather then system applications.

/proc   A virtual file system that allows users with privilege to monitor and modify kernel settings and configurations at run time.

Further reading:
 * FreeBSD Directory Structure
 * Linux Filesystem Hierarchy

So what has this to do with partitioning you ask? As was explained previously, the hierarchy was designed to involve multiple disks, partitions being logical disks, we can place some of these directories on their own file system and their own partition.

Its worth noting that: /etc, /bin, /sbin, /dev, and /lib MUST reside on the same partition as /.

Sizing
It is rather difficult to judge what size a partition should be. It takes a bit of experience but after thinking about the machine's intended purpose, one can usually get a pretty good idea of sizing needs. For example a computer used on a typical client machine would benefit from a large /home directory, while on a server /home should be considerably smaller.

Mount options
On Unix-like systems mount points are typically defined in /etc/fstab.

This is an example of a recently created fstab on a home server, in the fourth column, mount options are listed.

The options we are currently focused on include:
 * ro/rw
 * suid/nosuid
 * dev/nodev
 * exec/noexec
 * user(s)/nouser
 * auto/noauto
 * defaults

Certain file systems like /usr and /boot have been mounted with ro or read-only permission (in contrast to rw, read-write). This makes adding software or running updates slightly more painful by requiring an extra couple reboots. But the occasional difficulty means that accidentally deleted files arn't really deleted and malicious software has a harder time living through a reboot. There are also certain files that need to be written to, for example /etc/resolv.conf. For these files you can move them to a separate directory with write access and then place a symlink in their place.

Mounting a file system with nosuid can also add more grief to an administrator's life. But this disables the suid and sgui bits so that files can not run with the permissions of their owner. This makes it more difficult for privilege escalation attacks to be successful.

Using nodev disables special device files on that file system. The kind commonly found under /dev. Really you don't want these kinds of files anywhere but /dev, they can let an attacker break out of a chroot jail and bypass other restrictions.

Noexec is a tricky option to enable. It disables executable permissions, and is great to place on directories like /tmp. However, extracting compressed files, for example distfiles, requires executable permissions. This is why, at least on Gentoo systems, /var/tmp should be placed on its own partition. Disabling executable permissions on /var is usually a good idea but without /var/tmp on a separate partition software installation under Gentoo would be hampered.

Nouser requires that root mount the file system. Specifying user means that any user can mount the system but it implies; noexec, nosuid, and nodev unless explicitly overridden. Some systems offer the users option which is similar to user but there is a corresponding users group which a user must first be a member of to mount the file system.

In the example above, noauto is passed to the /boot partition. Noauto means that the file system is not automatically mounted at boot time, conversely auto explicitly mounts file systems at boot time. It is desirable to mount /boot as noauto so that should something ever happen, for example a power outage, your boot partition is not uncleanly unmounted. So that when you go to boot, the kernel image is safe and any recovery tools such as a statically compiled busybox can be used to repair any damage.

Defaults will typically replace all of the following permissions with one word; rw, suid, dev, exec, auto, nouser, async

Further Reading:
 * Arch Linux has a fairly in depth overview of fstab at their wiki: Arch Linux fstab wiki

Chroot
What is chroot exactly?

Chroot comes as both a shell utility and a system call. What chroot does is quiet simple, it changes the way programs see the root file system. For example running this command:

will make /mnt/foo the new / within the shell process that ran the chroot command. Essentially chroot is a primitive sandbox that is quick and easy to set up.

Why would anyone want to do this to the file system?

Traditionally chrooting was used to run daemons out of as a security measure. Today this is looked down upon slightly, modern tools like Linux cgroups and FreeBSD jails, both offer more complete sandboxing and thus more security then the humble chroot.

But good old chroot is quick, easy to setup, and often has configure script support in some more popular daemons such as BIND and Apache. We can easily use chroot to provide a safe build environment. Chrooting into an extracted Stage3 tarball offers an easy to set up, strip down, and rebuild environment to build and test new technologies without risking the destruction of your current workstation.

File System Check
The second letter was originally different. -Dennis Ritche on fsck

Fsck is a utility that can be run on a file system that is corrupt. With modern journaled file systems, fsck is not only much quicker but typically has a higher success rate when recovering from corruption. There are quite a few options one could pass to the fsck command including some gotchas, so reading over the manual page is highly recommended. A basic fsck command might look like this:

This will run a consistency check on the 8th partition of the first sata disk and automatically repair any issues if the file system supports that option.

Some important things to remember when using fsck:
 * Never run fsck on a mounted partition
 * lost+found is where orphaned files go
 * rebooting after fscking is usually healthy

Automatic fscking can also be configured. The 5th column in an fstab entry contains two numbers, the second number (labeled 'pass' in the example above) is the priority that a file system will be fscked after so many reboots. This thresh hold can usually be configured with a utility, for example tune2fs. A zero in this section forces a file system to not be checked, and the lower the number the higher its priority is.

RAID
RAID technologies are pretty strait forwards, take a few hard drives and string them together. RAIDs are defined by their level. For example RAID 0 is a system where two or more disks are combined so that there is additional storage and a disk I/O performance bonus. This documentation will discuss RAID level 5 and RAID level 6 which both offer some security.

RAID controller
What ties a RAID system all together is known as a RAID controller. RAID controllers can exist in software or hardware. The primary difference is that hardware RAID controllers off load processing to the RAID controller itself rather then on the central processing unit, which in some high performance environments can be beneficial. However in home systems or small businesses, often a software RAID controller is enough.

Often times a hardware RAID controller will have its own special configuration method so be sure to read the documentation provided. However in the Linux world a tool called mdadm is used for software RAID setups. mdadm is preferred over the older raidtools package, but it is worth looking into if you are using an older system or have special needs. To install mdadm on Gentoo Linux simply run:

Creating a software RAID
Quickly before proceeding to the meat and potatoes, lets talk about the difference between RAID 5 and RAID 6. RAID 5 requires a minimum of three physical disks, and is able to withstand the loss of one of those disks, but will take a performance hit until the failed disk is replaced and the RAID is synchronized. RAID 6 requires a minimum of four physical disks and can withstand the loss of two disks, and will only see a noticeable performance hit if two drives fail at the same time. Just like RAID 5, failed drives should be replaced and the RAID should be synchronized.

When deciding between RAID 5 and RAID 6, it is important to note that RAID 6 is favored. RAID 5 has a write hole, essentially under certain circumstances the RAID will fail to preserve data because a flaw in the RAID 5 algorithm. For that reason the following example will detail RAID 6.

First you need support in your kernel for RAID systems:

Next our disks need to be partitioned, assume we have four disks: sda, sdb, sdc, and sdd. Use your favorite partitioning tool to format the drives and create empty partition tables on them. Then allocate all the space in to a single partition. Finally we actually create the RAID:

You should now have a new device file, /dev/md0 which can be manipulated just like any other disk device file, however md0 represents the RAID that was just created.

We aren't quite done yet. The mdadm tool uses a configuration file located at /etc/mdadm.conf and while this is an optional step, editing this configuration file it is a recommended step. Instead of manually filling out this file, lets be lazy and run a couple commands instead:

This configuration file serves two purposes, first it helps to document the RAID which is very important when it comes time to replace a disk. And second it helps the kernel activate the RAID during boot instead of a user doing it manually. You are also encouraged to explore the monitor feature of mdadm, this sends mail warnings to administrators as issues with the RAID are encountered. A long with the monitor feature, a MAILADDR variable can be specified in /etc/mdadm.conf to give mdadm a mail address to send warnings to.

Maintaining a software RAID
There are a few commands and kernel data structures with which administrators dealing with a software RAID should be familiar.

To get details about the RAID run:

Here you will also see the progress of a RAID recovery or sync.

Occasionally, you will need to do a check for bad blocks on the RAID, reallocate the data stored on them, and then sync the RAID. To do this run:

To cleanly halt a RAID sync:

For troubleshooting and configuration purposes, there is an option to simulate a disk failure:

Replacing failed disks
In our simulation, the disk at /dev/sda1 failed. To fix it, all we have to do is remove it from the RAID logically and readd it to the RAID. When real hardware fails in reality the process is similar, except the additional step of replacing the failed hardware.

First logically remove the drive from the RAID:

At this point, in a real failure situation we would need to swap the failed disk. Depending on the hardware configuration we might have to power the system down all the way to accomplish this.

Note: If you are following this example, you should have created disks with a single partition on them. When a disk fails and this method was used, simply repeating the formatting process on any disk will allow it to be added to the RAID without issue. If RAW disks were used instead of partitions, then a replacement disk must be exactly the same model as the other disks in the RAID. To add a disk into the RAID as a replacement run this:

Once a new disk is added, the RAID should automatically begin rebuilding itself.

Quotas
Quotas are an important tool for administrators of multi-user systems. They allow you to prevent a group, user, or process (through group and user restrictions) from filling up disk space. This is particularly useful on for example a server that hosts a network share. Gentoo documentation already covers this topic in depth in their user and group limitations guide.

Encryption
Under construction

Permissions
Under construction

The Traditional Unix Way
In Unix, everything is a file. As such, permissions revolve around a series of file attributes. In a nutshell these attributes relate to a; read-bit, write-bit, executable-bit, setuid-bit, setgid-bit, sticky-bit, and information about owner, group, and world. Have a look at the out put of ls in this command:

In the third column you can see that root is the owner, and in the forth column root is also the group. Now lets look at the first column. The first dash indicates this is a file not a directory, otherwise there would be a d there, if an s where there it would indicate a socket file, and if it was an l it would be a link. The next three spaces indicate whether the read-bit(r), write-bit(w), or executable-bit(x) is set for the owner on this file. The next three denote the same permissions bits but for the group owner instead of the user owner, and the third group of three denote permissions for the world, or everyone else on the system. This is the basic Unix permissions model.

Lets look a little deeper. Grasping your basic permissions bits are usually pretty easy, but setuid and setgid bits are a little trickier to beginners and considerably more dangerous if used incorrectly. But if used correctly, setuid and setgid bits can make system management much easier by making permissions more flexible. Essentially the setuid (set user id) bit when activated, will allow the file to be executed with the permissions of its owner by anyone. As you might have already guessed setgid (set group id) will allow any user to execute a file with the permissions of its group.

The logic here, is that this allows administrators to give users access to particular programs that would otherwise need privileged without handing out the root password and allowing them full access to the rest of the system. With the ls command, the x denoting user executable permission will be replaced with an s if the setuid-bit is set. Naturally this means that in the group permission section, an s will replace the x if the setgid-bit is set.

Deeper still, we have the sticky-bit. The sticky-bit can be very confusing, while traditionally it had a very clear usage, that usage has evolved over time and now many different flavors of Unix have as many different uses for the sticky-bit. On Linux the sticky bit can be set on directories, and any files in this directory can only be deleted or unlinked by the owner. If the sticky-bit is set, a t will be displayed at the far right of the user-group-world permissions listing in ls output.

Managing permission bits, bit wrangling
Being able to wrangle all these permissions bits is a very important job for systems administrators. The tools of the trade are; chmod, chown, chgrp, and umask.

Backups
Under construction, lightly discuss, link to existing Gentoo wikis