ServersPerchild: Setting Users and Groups per Virtual Host Page 2

Perchild: Setting Users and Groups per Virtual Host Page 2




The

obvious question now, is how does this work internally. The Perchild

MPM has a special global table which it uses to start children and

allow those children to change to the correct user Ids. It

also uses the per-server configuration to pass requests between child

processes. When the MPM encounters a ChildPerUserID directive it

begins to fill out the global child table. Each child process gets

one place in the table, which stores the User and Group Id that the

child should run as. The table also stores a socket descriptor, but

it isn’t filled out until later.

While

parsing the configuration for each VirtualHost, if the server

encounters an AssignUserId directive, it fills out a perchild

per-server configuration structure, which contains the two socket

descriptors. In order to do this, the server creates a set of

anonymous Unix Domain Sockets which are used to pass the request

between processes. After the sockets are created, the server

searches the child table to find the child processes that have the

same User and Group Ids. Once found, one of the socket descriptors

is attached to all of the processes with that User Group combination.

Both socket descriptors are attached to the specific VirtualHost
that is being configured. This step is repeated for all

VirtualHosts. Once all VirtualHosts have been configured, the server

ensures that each host has been assigned a socket. If not, the

server creates a set of default sockets and stores those in any

server that doesn’t already have a socket.

The next

step is to create the child processes. When each process is started,

it checks the global child table, and switches to the appropriate

User and Group Ids. If no User and Group Id are specified for this

child process, then the User and Group specified in the main server

are used. Each child also adds the socket in the socket table to the

list of sockets it will poll on. From here, child startup proceeds

as normal with each child process polling on all of the ports opened

in the parent process. This leaves the server looking like Figure 1.

Figure 1

Figure 1.

When a

request comes in, the Perchild MPM is the first module called in the

post_read_request phase. During this phase, the Perchild MPM ensures

that the request is for the current child process. If so, processing

continues as normal. If not, the child process uses the VirtualHost

that is attached to the request to find the correct Unix Domain

Socket to use. The child process begins by finding the socket that

is currently being used to communicate with the client in the

connection structure. Once this socket is found, it is passed to the

correct child process through the Unix Domain socket (S1 or S2 in the

diagram). Finally, the part of the request that has already been

read from the client is sent to the new child over the Unix Domain

socket. The original child process then closes its connection to the

client, and longjmps out of the post_read_request phase to the end of

processing a request. This thread then goes back to listening for

another new request.

Latest Posts

Related Stories