![]() ![]() |
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).[3] 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:
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.[4]
10.1.1 Test seteuid and setreuidClearly, 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:
Note that setreuid(3) is preferred over seteuid(3)[5] 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 Further consider that these files both have permissions of set-user-id to the individual users[6] and are writable only by the individual users. To perform delivery in this instance, sendmail must[7] 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. |
![]() ![]() |