Process Layout

As outlined in the Privilege Separation section of this document pyttpd spawns multiple subprocesses. Subprocesses are spawned only during initialization or configuration reloads. This is done because fork’ing is considered to be a costly operation.

Each of these processes belongs to one of the following process categories:

Privileged Master Process (pmaster)

The Master Process is a single process that represents the top of pyttpd’s process tree. It should be run as superuser, to allow binding to privileged ports (<1024), and set the UIDs and GIDs of subprocesses it spawns. Funtionality of this process should be kept as minimal as possible, as it forms the number one target for attacks.

Except for the needed configuration file parsing no other parsing must be done by this process, to minimize attack vectors.

Its sole purpose is

  • parsing the master configuration file,
  • the individual listener and vhost process configuration files,
  • binding to privileged ports,
  • spawning all unprivileged processes with their individual credentials and
  • forwarding listener FDs to listener processes,
  • providing the unprivileged master process with FDs to and information about all other processes and
  • monitoring the status of each and every child process and taking action when a child process dies.

Unprivileged Master Process (umaster)

The unprivileged master process is spawned by the privileged master process and is responsible for routing requests incoming from listener processes to the responsible vhost processes and the responses back.

It thus is provided with a hostname-to-vhost-process mapping by the pmaster process.

Listener Process

The listener processes are responsible for

  • accepting incoming connections on a single port,
  • parsing the requests and
  • forwarding the parsed information to the umaster process.

These processes must run as an unprivileged user, so to reduce the possible effects of a successful attack. It is also recommended to run one process per socket, so not to create a single point of failure and thus provide a great target for attacks.

Vhost Process

The responsibility of virtual host processes is handling requests coming in from the umaster process and sending back replies.

It is required that theses processes run as unprivileged users, reducing the possible effects of attacks, just as listener processes do.

Vhost processes make use of a worker thread pool to process requests in separate threads. However, a new thread should only be spawned in case the load on all worker threads is too high, as creating a thread is, just like fork’ing, considered to be a costly operation.

Additionally subprocesses for SCGI or FastCGI applications may be spawned, but just as all other pyttpd subprocesses, only at initialization or configuration reload time.