2012-03-26
What it means to become another user on Unix
Ignoring things like SELinux for the moment, the basic security state of Unix system calls has always been that root is allowed to become any other UID at will, but no one else is allowed to change their UID or other security attributes (setuid programs then provide an escape hatch from this). But what does it mean to become another user on Unix, beyond just setting your UID? In fact there are a whole series of things that it can mean, some of which you do not necessarily want.
Let's make a list:
- switching to the user's UID. This is the basic prerequisite of what
it means to become another user on Unix, and is done by
setuid(). - switching your groups to the user's groups, which is done with a
combination of
initgroups()andsetgid(). - setting some environment variables like
$HOMEand$SHELLto values appropriate for the new user.(Most but not all versions of
sudo this. Versions ofsuthat do not change$HOMEcan be exciting, especially when combined with shells that read initialization files from$HOME.) - clearing various environment variables; in the extreme case, you will
clear all environment variables and give yourself a new set of safe
values for things like
$PATHand so on.(Aggressively scrubbing the environment is generally the default for
sudo. In general there are any number of environment variables that are very dangerous to leave intact, such as all of theLD_*variables that influence the behavior of the dynamic loader.) - running the user's shell, either interactively or with
-c ...to execute commands.(
sunormally always runs the user's shell;sudowill often run commands directly without starting the user's shell.) - changing to the user's home directory.
- running the user's shell as a login shell.
- allocating a new pseudo-tty as the user and attaching the user's shell
and so on to it as a new session. This is generally the domain
of things that are making real login sessions, like
sshd, instead of programs that just become the user.
(Note that this list is not in the order that your code wants to
actually do these operations. For example, you want to set groups
before changing to the other UID because the moment you setuid() to a
non-root user you lose the power to set your own groups list.)
Many things that become another user deliberately run the the target
user's shell even when they just want to run a command. This is done
partly so that the user's shell can do any special initialization that,
eg, may augment its $PATH and partly so that users with restricted
shells can't escape them in various clever ways. However, not everything
does this and sometimes running the user's shell is inconvenient.
There are a surprising number of cases where you want basically the
first two only; you want to run a command as a user but in a way
such that their environment (their shell, their shell initialization,
and so on) is ignored. It's possible to do this with standard
commands like su and sudo by carefully reading their manpages
and picking exactly the right options, but I find it easier to have
a very basic runas program sitting around.
(runas only works for root, so it can completely ignore authentication
and similar issues.)
2012-03-21
My view of where the Unix community is
I've written before about how there once was a time when Sun could be seen as the heart of the Unix community (cf), and this view of Sun's place in the community is why some people don't like Oracle's Sun-related actions (cf the commentator here). As I wrote back then, my feelings about Sun are somewhat more complicated and tangled (cf) because I don't think that Sun has been the heart of the Unix community for a long time.
There's a lot of reasons that Sun stopped being the center of the Unix community (and maybe I'll write about them sometime), but the important thing is that it did not happen this decade or even this century. Sun ceased being the center in the mid 1990s, when it increasingly had only tired hardware and tired software to offer. Even back then, it was not hard to see where the community was going if you paid attention: it was going to x86 systems, because they were good enough and cheap.
(I don't have a clean and clear definition of the Unix community, but to me it is some mixture of the people using Unix, the people enthused about Unix, and the people who are evolving Unix and moving it forward. Mostly the latter two, really; you need to be interested in Unix as itself in order to really be part of the community instead of just a passive user of computing. This is why most of the OS X people don't count.)
Thus it's clear to me that today's Unix community is found in either FreeBSD or Linux. The part of the community that likes Unix as it is has mostly wound up in FreeBSD; the part of the community that has radical dreams for the future has mostly wound up in Linux (this is where it's appropriate to borrow a Henry Spencer quote and say 'those who don't understand Plan 9 are condemned to reinvent it, poorly'). This is not a new development; it's been this way since no later than the late 1990s.
(My somewhat inflammatory view is that while many of the people of the old Unix community who stayed around Unix seem to have wound up in the *BSDs, the spirit of the Unix community mostly settled in Linux. Unfortunately there are significant drawbacks to this split, some of which I have captured in my borrowed witticism.)
Sun's death and absorption by Oracle was not a real loss for the Unix community because Sun hasn't been important to the real Unix community for some time. The real Unix community is going on just as it has been for years, and is probably roughly as healthy as it ever has been.
Sidebar: why the Unix community is not in all of the *BSDs
OpenBSD is not where the Unix community is today because its scope is too small, although valuable. NetBSD and DragonFly are simply too small, period. Only FreeBSD is large and encompassing enough.
2012-03-15
Part of the cleverness of Unix permissions (a little thought)
Ever since it's become popular to add various sorts of advanced permissions schemes to Unixes (ACLs, for example), it's struck me that part of the genius of Unix permissions is that they are short.
I don't particularly mean short in storage terms (although that didn't hurt Unix in the early days). I mean short more in the sense of 'simple'; Unix permissions are simple enough that they have a short, clear representation. You can describe the basic access permissions for a file with three relatively short strings (the actual permissions plus who the owner and group of the file is), and these strings are mostly self-contained.
(You don't necessarily know who is in the group without running a command.)
I think that this shortness is an important part of why Unix permissions
work relatively well. Short permissions are easy to display (which means
that they can be displayed routinely, for example in 'ls -l' output)
and relatively easy to understand. Because they are simple, they have
few surprising interactions. I'll even go so far as to say that short,
simple permissions are relatively easy to manipulate.
(There are aspects of Unix permissions that are not easy to understand and predict, things like what even the permission bits mean on directories, what the various obscure permission bits mean on everything, and so on. But I tend to think that this just adds complexity around the edges, not in the center.)