Making and Mounting a File System

This lesson discusses how we can assemble a full directory tree from many underlying file systems.

We'll cover the following

We’ve now toured the basic interfaces to access files, directories, and certain types of special types of links. But there is one more topic we should discuss: how to assemble a full directory tree from many underlying file systems. This task is accomplished via first making file systems, and then mounting them to make their contents accessible.

Making a file system

To make a file system, most file systems provide a tool, usually referred to as mkfs (pronounced “make fs”), that performs exactly this task. The idea is as follows: give the tool, as input, a device (such as a disk partition, e.g., /dev/sda1) and a file system type (e.g., ext3), and it simply writes an empty file system, starting with a root directory, onto that disk partition. And mkfs said, let there be a file system!

Mounting a file system

However, once such a file system is created, it needs to be made accessible within the uniform file-system tree. This task is achieved via the mount program (which makes the underlying system call mount() to do the real work). What mount does, quite simply is take an existing directory as a target mount point and essentially paste a new file system onto the directory tree at that point.

An example here might be useful. Imagine we have an unmounted ext3 file system, stored in device partition /dev/sda1, that has the following contents: a root directory which contains two sub-directories, a and b, each of which in turn holds a single file named foo. Let’s say we wish to mount this file system at the mount point /home/users. We would type something like this:

Press + to interact
prompt> mount -t ext3 /dev/sda1 /home/users

If successful, the mount would thus make this new file system available. However, note how the new file system is now accessed. To look at the contents of the root directory, we would use ls like this:

Press + to interact
prompt> ls /home/users/ ab

As you can see, the pathname /home/users/ now refers to the root of the newly-mounted directory. Similarly, we could access directories a and b with the pathnames /home/users/a and /home/users/b. Finally, the files named foo could be accessed via /home/users/a/foo and /home/users/b/foo. And thus the beauty of mount: instead of having a number of separate file systems, mount unifies all file systems into one tree, making naming uniform and convenient.

To see what is mounted on your system, and at which points, simply run the mount program. You’ll see something like this:

Press + to interact
/dev/sda1 on / type ext3 (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
/dev/sda5 on /tmp type ext3 (rw)
/dev/sda7 on /var/vice/cache type ext3 (rw)
tmpfs on /dev/shm type tmpfs (rw)
AFS on /afs type afs (rw)

This crazy mix shows that a whole number of different file systems, including:

  • ext3 (a standard disk-based file system),
  • the proc file system (a file system for accessing information about current processes),
  • tmpfs (a file system just for temporary files),
  • AFS (a distributed file system) are all glued together onto this one machine’s file-system tree.

TIP: BE WARY OF TOCTTOU

In 1974, McPhee noticed a problem in computer systems. Specifically, McPhee noted that “… if there exists a time interval between a validity-check and the operation connected with that validity-check, [and,] through multitasking, the validity-check variables can deliberately be changed during this time interval, resulting in an invalid operation being performed by the control program.” We today call this the Time Of Check To Time Of Use (TOCTTOU) problem, and alas, it still can occur.

A simple example, as described by Bishop and Dilger“Checking for Race Conditions in File Accesses” by Matt Bishop, Michael Dilger. Computing Systems 9:2, 1996. A great description of the TOCTTOU problem and its presence in file systems., shows how a user can trick a more trusted service and thus cause trouble. Imagine, for example, that a mail service runs as root (and thus has privilege to access all files on a system). This service appends an incoming message to a user’s inbox file as follows. First, it calls lstat() to get information about the file, specifically ensuring that it is actually just a regular file owned by the target user and not a link to another file that the mail server should not be updating. Then, after the check succeeds, the server updates the file with the new message.

Unfortunately, the gap between the check and the update leads to a problem: the attacker (in this case, the user who is receiving the mail, and thus has permissions to access the inbox) switches the inbox file (via a call to rename()) to point to a sensitive file such as /etc/passwd (which holds information about users and their passwords). If this switch happens at just the right time (between the check and the access), the server will blithely update the sensitive file with the contents of the mail. The attacker can now write to the sensitive file by sending an email, an escalation in privilege; by updating /etc/passwd, the attacker can add an account with root privileges and thus gain control of the system.

There are not any simple and great solutions to the TOCTTOU problem [T+08]. One approach is to reduce the number of services that need root privileges to run, which helps. The O_NOFOLLOW flag makes it so that open() will fail if the target is a symbolic link, thus avoiding attacks that require said links. More radical approaches, such as using a transactional file system“TxFS: Leveraging File-System Crash Consistency to Provide ACID Transactions” by Y. Hu, Z. Zhu, I. Neal, Y. Kwon, T. Cheng, V. Chidambaram, E. Witchel. USENIX ATC ’18, June 2018. The best paper at USENIX ATC ’18, and a good recent place to start to learn about transactional file systems., would solve the problem, there aren’t many transactional file systems in wide deployment. Thus, the usual (lame) advice: careful when you write code that runs with high privileges!

Get hands-on with 1400+ tech skills courses.