@@ -19,6 +19,10 @@ import (
1919 "github.com/opencontainers/runc/libcontainer/utils"
2020)
2121
22+ // Synchronisation value for cgroup namespace setup.
23+ // The same constant is defined in nsexec.c as "CREATECGROUPNS".
24+ const createCgroupns byte = (1 << 7 )
25+
2226type parentProcess interface {
2327 // pid returns the pid for the running process.
2428 pid () int
@@ -224,12 +228,17 @@ func (p *initProcess) externalDescriptors() []string {
224228 return p .fds
225229}
226230
227- // execSetns runs the process that executes C code to perform the setns calls
228- // because setns support requires the C process to fork off a child and perform the setns
229- // before the go runtime boots, we wait on the process to die and receive the child's pid
230- // over the provided pipe.
231- // This is called by initProcess.start function
232- func (p * initProcess ) execSetns () error {
231+ // getChildPid receives the final child's pid over the provided pipe.
232+ func (p * initProcess ) getChildPid () (int , error ) {
233+ var pid * pid
234+ if err := json .NewDecoder (p .parentPipe ).Decode (& pid ); err != nil {
235+ p .cmd .Wait ()
236+ return - 1 , err
237+ }
238+ return pid .Pid , nil
239+ }
240+
241+ func (p * initProcess ) waitForChildExit (childPid int ) error {
233242 status , err := p .cmd .Process .Wait ()
234243 if err != nil {
235244 p .cmd .Wait ()
@@ -239,12 +248,7 @@ func (p *initProcess) execSetns() error {
239248 p .cmd .Wait ()
240249 return & exec.ExitError {ProcessState : status }
241250 }
242- var pid * pid
243- if err := json .NewDecoder (p .parentPipe ).Decode (& pid ); err != nil {
244- p .cmd .Wait ()
245- return err
246- }
247- process , err := os .FindProcess (pid .Pid )
251+ process , err := os .FindProcess (childPid )
248252 if err != nil {
249253 return err
250254 }
@@ -266,22 +270,35 @@ func (p *initProcess) start() error {
266270 if _ , err := io .Copy (p .parentPipe , p .bootstrapData ); err != nil {
267271 return err
268272 }
269- if err := p .execSetns (); err != nil {
270- return newSystemErrorWithCause (err , "running exec setns process for init" )
273+ childPid , err := p .getChildPid ()
274+ if err != nil {
275+ return newSystemErrorWithCause (err , "getting the final child's pid from pipe" )
271276 }
272277 // Save the standard descriptor names before the container process
273278 // can potentially move them (e.g., via dup2()). If we don't do this now,
274279 // we won't know at checkpoint time which file descriptor to look up.
275- fds , err := getPipeFds (p . pid () )
280+ fds , err := getPipeFds (childPid )
276281 if err != nil {
277- return newSystemErrorWithCausef (err , "getting pipe fds for pid %d" , p . pid () )
282+ return newSystemErrorWithCausef (err , "getting pipe fds for pid %d" , childPid )
278283 }
279284 p .setExternalDescriptors (fds )
280285 // Do this before syncing with child so that no children
281286 // can escape the cgroup
282- if err := p .manager .Apply (p . pid () ); err != nil {
287+ if err := p .manager .Apply (childPid ); err != nil {
283288 return newSystemErrorWithCause (err , "applying cgroup configuration for process" )
284289 }
290+ // Now it's time to setup cgroup namesapce
291+ if p .config .Config .Namespaces .Contains (configs .NEWCGROUP ) && p .config .Config .Namespaces .PathOf (configs .NEWCGROUP ) == "" {
292+ if _ , err := p .parentPipe .Write ([]byte {createCgroupns }); err != nil {
293+ return newSystemErrorWithCause (err , "sending synchronization value to init process" )
294+ }
295+ }
296+
297+ // Wait for our first child to exit
298+ if err := p .waitForChildExit (childPid ); err != nil {
299+ return newSystemErrorWithCause (err , "waiting for our first child to exit" )
300+ }
301+
285302 defer func () {
286303 if err != nil {
287304 // TODO: should not be the responsibility to call here
0 commit comments