Create child processes problem

Coordinator
Aug 4, 2007 at 10:41 PM
Edited Aug 4, 2007 at 11:04 PM
To create and add child process to a job in a secure manner, we need to first create the child process with the CREATE_SUSPENDED flag set, assign the new process to the job and then resume the process. The problem: .Net System.Diagnostics.Process.Start method has no CreateSuspended flag. To overcome the problem we can choose one of these solutions:

  1. Create the process using Win32 CreateProcess
  2. Create the process without suspending it
  3. Create a child process; add the child process to the job. Use the child process to create process in the job.

The first approach solves the problem, but it does not support all System.Diagnostics.Process abilities such as the ability to redirect standard input, output and error to a stream.
The second approach is the easiest one. It gives the best performance and it supports all .Net Process class abilities, but it does not solve the problem. Child process may create a grandchild process before it assigned to the job. It can also assign itself to other job preventing the creator process entering it to the original job object.
The third approach solves the problem and gives all .Net Process class abilities. But it is much more complicated. We have to spawn a child process as an activation service. We need to know that it entered the Job before we ask it to create the grandchild process. We need to communicate with it whenever we'd like it to create a new process in the job. To start a grandchild process we need to pass the ProcessStartInfo instance, but it is not [Serializable] , so we have to wrap it with another class. When we create a grandchild process we need to get back the Process instance. The Process class is marshal by ref class, so we can get a remote proxy to it.

Yes, all of this because the CLR team forgot to wrap the CREATE_SUSPANDED flag.

Solution:
To overcome this problem, I choose to implement approaches 2 and 3:

 
//Create a process in a Job Object sandbox, If the newly created process creates a child process before entering the job, the child process will not be part of the job.
System::Diagnostics::Process ^CreateProcessMayBreakAway(System::Diagnostics::ProcessStartInfo ^startupInfo);
 
//Create a process in a Job Object sandbox, the method uses other process to create the child process
System::Diagnostics::Process ^CreateProcessSecured(System::Diagnostics::ProcessStartInfo ^startupInfo);
 

CreateProcessMayBreakAway Is straight forward, Just using Process.Start and AssignProcessToJob

CreateProcessSecured Is much more complicated. It uses a C# based executable project. After starting it, we communicate with it using remoting IPC channel. We ask it to create process in the job.

I decided not to hide this implementation from the user. This means that this activation service is part of the job. If the user sets a maximum active processes limit, she has to consider this one. She also has to know that if she terminates all the processes in the Job, the activation service will be terminated too. (New activation service will be created on demand when it is needed).
I would like to see if anyone has better solution.

Alon