Postfix NoNewPrivileges support


Introduction

This document presents an alternative privilege elevation mechanism for systems that disable set-gid privilege elevation.

Postfix user request architecture

Historically, a user request travels through three security zones on its way to a Postfix core daemon process:

Architectural properties with set-gid privilege elevation

The setgid-based, three-zone, architecture has several key benefits. These will need to be preserved on systems that don't support set-gid privileges:

Alternative privilege elevation with postlift(8)

Some systems disable set-gid privilege elevation, for example using "NoNewPrivileges=yes" or the "nosuid" file system mount option. On these systems, Postfix may use an alternative privilege elevation method that is implemented with the postlift(8) service, changing the architecture as shown below. As of Postfix 3.12, this alternative method is supported only on Linux environments using systemd.

Zone 1
user UID
user GID
Zone 2
"postdrop" UID
"postdrop" GID
Zone 3
"postfix" UID
"postfix" GID
mail(1)
mailx(1)
sendmail(1)
mailq(1)
-> postdrop(1)
postlog(1)
postqueue(1)
-> postlift(8) -> postdrop(1)
postlog(1)
postqueue(1)
-> pickup(8)
postlogd(8)
qmgr(8)
flush(8)
showq(8)

When set-gid privileges are disabled, a postdrop(1), postlog(1), or postqueue(1) client process with Zone 1 privileges will connect to the Zone 2 postlift(8) service, requesting that postlift(8) runs the same command (postdrop(1) etc.) in a process with Zone 2 privileges. This allows the elevated process to add a message to the protected maildrop queue, or to interact with a Zone 3 core daemon process. postlift(8) propagates the exit status from the elevated process back to the Zone 1 client process.

The super-user ("root") is excluded from postlift(8) privilege elevation. Because root already has sufficient privileges, its Zone 1 postdrop(1), postlog(1), or postqueue(1) processes can directly access the maildrop queue or a Zone 3 process. This eliminates a postlift(8) start-up dependency and avoids some implementation complexity.

Architectural properties with postlift(8) privilege elevation

The alternative architecture can provide benefits comparable to the architecture based on set-gid privilege elevation:

Systemd integration

To run postlift(8) under systemd, follow the steeps below:

Future work: spawn(8) integration

On systems without systemd, partial functionality may be implemented using the Postfix spawn(8) service. Historically, this service accepts connections on a private or public (but still protected) socket, and executes a configured program with specific privileges. Making this work with postlift(8) requires additional Postfix features:

A down-side is that a spawn(8) daemon remains unavailable until Postfix starts. Consequently, Zone 1 email submissions from non-root processes will fail to enter the queue while Postfix is not running, either during maintenance or during system start-up. Because Postfix typically launches with a "network" or "multi-user" start-up target, early boot-time email messages from non-root users may be dropped.

Credits