The suidperl Story

Once upon a time, long, long ago and far, far away, a Linux programmer cut a corner. What corner was that? I didn't know programs had corners; they must get dusty. Anyway, she made the assumption that a mounted filesystem uses the same set of users and groups as the main filesystem. (One must recall that, according to someone I know, to assume is to make a, well, let me continue, out of u and me). This assumption was fine if the system administrator decided to spread out a Linux installation over some 50 different disk partitions (one for Firefox, one for Eclipse, one for OpenOffice...).

But then people decided they wanted to use floppy disks. And someone put a file on a disk at home only to discover that, even after the administrator had kindly mounted the disk for him, he couldn't read the file at school because he had a different user ID. He got mad; this was absurd, especially because he had physical control of the disk and could do anything he liked with it if he only had a computer that would cooperate with him. (Or a really good microscope, a really steady hand and a really tiny magnet.)

The trouble, really, was that the system at school treated the disk as part of itself. This meant two things. First, the system defended the disk against its true owner. Second, the system trusted the disk. When the unlucky user realized this, he got revenge. He brought the disk home (where, even though he used his personal account for most things, he had root power over the computer). He copied bash to the disk and made it setuid-root. Then he brought the magic disk to school and popped it in the computer. By that time, the school's computers had fancy user mounting software. He mounted the disk, ran bash -p, and got his revenge.

Linux developers realized this was a problem and added the nosuid mount option, which inactivates setuid and setgid bits on a filesystem. Then they thought hard and realized that they also needed a nodev option: don't let device files behave specially. These two options were to be used together on "untrusted" filesystems, and all the automounters learned to use them.

Linux ignores setuid bits on scripts. That decision came after someone discovered this wonderful little hack. Hard link (or even symlink) to someone's setuid script. Invoke, and as the interpreter is coming up, swap the link for another script of your own choosing. The kernel uses $0 to get the script to the interpreter, but if it makes a temporary file or a pre-opened file descriptor with $0 == /dev/fd/x, $0 is wrong. There's no good answer.

But some people really wanted setuid bits on their scripts! Especially Perl scripts. So suidperl was written. A system administrator who wants to provide setuid Perl installs this program setuid-root. When suidperl is used to invoke a script, it changes to appropriate user IDs first, honoring any set?id bits on the script. One supposes that it opens the script and then uses fstat to prevent the attack mentioned above.

But, alas, suidperl used some kind of stat, not the function whatIdsDoIUseToExecuteThisFile that I imagine must exist in the kernel somewhere. So our hacker from earlier played the exact same trick, but with a Perl script. And then suidperl was fixed. I wonder how they did it.

All this trickery provided a way not to trust mounted filesystems, but no one has come up with a way not to protect them from their mounters, the other side of the coin. So let me propose the following. Anyone owning a device file or filesystem and a mount point may mount (the system allocates a loopback device if needed). That person has superpowers over that filesystem, just as root traditionally has over /. This deals with "no protection"; the "no trust" is left.

Set-id is honored only if the mounter has, or could gain, the authority of the target user or group. A device node is honored if and only if the mounter could have created it on the root filesystem. Furthermore, although the mounter can see the full range of users and groups on the filesystem (though they be interpreted by the system outside), to others it looks like all the files belong to the mounter.

In some situations, mere ownership of a file by a certain person might be given weight, as when the file contains data considered "illegal", a third way in which filesystems are "trusted" that, it seems, no one has considered before. To deal with this, only the mounter can see the true UIDs and GIDs on the filesystem. Other people see a file's UID or GID if and only if the mounter could gain the authority of the user or group; otherwise, the mounter's UID and/or default GID show. (It might be nice if the system also translated the rogue UIDs/GIDs to POSIX ACLs so that the "owners" would understand why they seem to have access to the file.)

Filesystems in Userspace is a popular software package that provides the sort of free-for-all mounting described above as a special case. However, it lets the user mount on any directory (s)he can write without restriction; I think (s)he should own the mount point. It also imposes the crushing restriction that no user may access a filesystem mounted by another user. This is to avoid having to consider trust associated with file ownership and to save programs from finding themselves in filesystems with wacky semantics. It is true, however, that many more issues should probably be considered before it is safe for one user's filesystem to be used by other users. Soon to come, with an elegant model (Arenas) inspired by all the above considerations, is Object Logistics. I did a Google search right now (2005.08.01 19:36:42 EDT) and the name "Object Logistics" in the context of an object system appears to be Internet-unique.