10.1 Why root?
One common complaint
about sendmail centers on the fact that it is
often run set-user-id root
(that is, run as root no matter who actually
runs it). Beginning with V8.12, the default is to run
sendmail as a user other than
root (Section 2.6.2). The
listening daemon needs to be root, but
sendmail itself no longer needs to be
set-user-id root.
For the most part it is necessary for sendmail
to run as root to satisfy legitimate needs.
Consider the following:
Users want ~/.forward files to work even when
their home directory is set to mode 700. The
sendmail program requires
root privilege so that it can temporarily become
the user to read and process the ~/.forward
file.
Users want :include: mailing-list files readable
only by themselves and sendmail. The
sendmail program requires
root privilege so that it can temporarily become
the owner of the list.
Users want programs that run on their behalf to run as themselves.
This requires root privileges, and running as
anything else would be potentially very dangerous.
Users want sendmail to listen on TCP/IP ports
that are common (ports 25 and 587). The sendmail
program requires root privilege so that it can
initiate listening connections to privileged ports.
Some folks have been tempted to run sendmail as
an untrusted pseudo-user (such as nobody). But
this doesn't really work. For example, it causes
programs in users' ~/.forward
files to be run as nobody, and it requires the
queue to be owned by nobody. Consequently, such
a scheme allows any user to break into and modify the
queue.
10.1.1 Test seteuid and setreuid
Clearly, many of
sendmail's duties require it to
run as root. As a corollary, however, whenever
sendmail does not need to be
root, it should become the appropriate
non-privileged user. It does this by using the following bit of
logic:
If it was compiled with support for seteuid(3)
(USESETEUID), use that routine to set the effective
uid to that of the desired
non-root user. This is less preferred than the
following.
If it was compiled with support for setreuid(3)
(HAS...), use that routine to set the effective
and real uids to those of the desired
non-root user.
Otherwise, use setuid(3) to become the desired
non-root user.
Note that setreuid(3) is preferred over
seteuid(3) and
setuid(3) because it allows
sendmail to temporarily give away both its real
and effective root privilege, then to get it
back again. To illustrate the need for this behavior, consider
processing a mailing list that saves mail to two different files:
/u/bill/archive owned by the user bill, mode 4600
/u/alice/archive owned by the user alice, mode 4600
Further consider that these files both have permissions of
set-user-id to the individual users and are writable only by the individual
users. To perform delivery in this instance,
sendmail must first become
bill (this requires root
privilege). To become another user, sendmail
forks. The parent remains root and the child
becomes the user, bill in our example. When it
is done, the child exits. The parent sendmail
remains root so that it can next become
alice. By retaining a real
uid of root,
sendmail is able to change its effective
uid to one user after another as needed.
See the description of the test directory in
USESETEUID for more on this subject.
|