2009-03-26
An important difference
As a note to myself, there is an important difference between
; timeio 10G </dev/zero >somefile ; timeio <somefile
and what I actually intended to do for the second command,
; timeio <somefile >/dev/null
Forgetting this difference has several times left me wondering why disk IO read rates on test systems seemed to have dropped by several orders of magnitude from what they should be for no apparent reason. (Since writing null bytes to your screen is a great way to burn CPU and possibly network bandwidth while doing nothing visible at all.)
(Why I have my own command to measure bulk IO performance is a topic for another entry.)
2009-03-14
Why I don't trust seteuid() and friends
Unix has a number of methods that a suitably privileged process can
use to temporarily assume another UID, do something with those limited
privileges, and then return back to its old, fully privileged state.
The grandfather of these is probably setreuid(), which appeared
way back in 4.2 BSD.
Normally, there are any number of ways to examine and interfere with
processes that are running under your UID; you can send them signals,
you can stop them, you can use ptrace() or the equivalent to inspect
them, run them as slow as you want, and even inject your own code, and
on some operating systems you can use /proc to gain access to files
that they have open. (This is not an exhaustive list.)
Allowing you to do any of these to a process that is merely temporarily running with your UID and that actually had elevated privileges opens up various sorts of security holes. If you can directly inject code it is an instant 'game over', but even lesser access is dangerous; for example, such a process may have open file descriptors to files that contain sensitive information (which it has left open because it was counting on them staying inaccessible to you).
In theory, Unix kernels prevent you from doing any of these things to such processes. In practice, people keep adding ways to do things to your processes (and sometimes they add new ways to do things with less privileges), and they do not always realize the full implications or, even if they do, they do not completely protect their mechanism.
The result, at least in my impression, has been a slow stream of ways to make such temporarily reduced privileges 'leak', to exploit them to gain extra access or information or the like. As a result I do not trust any of them to be completely secure all of the time. Which leads me to my view that if you want complete security on Unix, you must irrevocably give up all privileges.
On some systems, even many systems, your code will be safe today if you properly use the right mechanism to temporarily assume another UID (note all of those qualifiers). But I cannot trust it to stay safe tomorrow and on another system, because I feel that the whole edifice is simply too fragile. Irrevocably giving up privileges is harsh, but it is not fragile, and it is honest; when you write such code, you write it with the full knowledge that the user can completely hijack your unprivileged side, and the rest of your code has to be able to deal with that.
2009-03-12
The not so secret history of /var
Originally, Unix had no /var; what is currently put there went
into /usr instead (with some of it going into /etc), so you had
/usr/log, /usr/spool, /usr/tmp, and so on. Remnants of this
era still linger on in /etc, where you still find a certain number of
frequently updated data files like /etc/passwd.
(One might sensibly ask why Unix had both /tmp and /usr/tmp. My
guess is that it goes back to the days before /usr, and so /tmp had to be retained when /usr was
added but at the same time people wanted a bigger scratch space, so
/usr/tmp was created.)
Then along came the idea of diskless workstations (I believe originally
from Sun). Even back then, /usr was the biggest system filesystem, so
no one was really enthused about the idea of each diskless system having
its own copy. Since at this point symlinks had been introduced, people
came up with the idea of moving everything writable from /usr into a
new filesystem, /var, and leaving symlinks behind so that people and
programs could continue to use old paths like /usr/tmp. This left
/usr read-only and shareable among all of your diskless clients,
which saved a lot of disk space.
(Indeed, a shared /usr and the accompanying disk space savings
are probably what made diskless clients viable in the first place.)
Over the years since then, the symlinks have been progressively removed on many systems. But today you can still find them on some systems that especially value backwards compatibility, for example Solaris 10.
In addition to moving things from /usr to /var, a certain number of
things were relocated from /etc to /var. Practically speaking this
was much less important, since you needed a separate / filesystem for
each diskless client anyways, but it did create a culture where system
daemons shouldn't normally write to /etc to store PID files and so on.