@@ -350,6 +350,23 @@ func (c *linuxContainer) deleteExecFifo() {
350350 os .Remove (fifoName )
351351}
352352
353+ // includeExecFifo opens the container's execfifo as a pathfd, so that the
354+ // container cannot access the statedir (and the FIFO itself remains
355+ // un-opened). It then adds the FifoFd to the given exec.Cmd as an inherited
356+ // fd, with _LIBCONTAINER_FIFOFD set to its fd number.
357+ func (c * linuxContainer ) includeExecFifo (cmd * exec.Cmd ) error {
358+ fifoName := filepath .Join (c .root , execFifoFilename )
359+ fifoFd , err := unix .Open (fifoName , unix .O_PATH | unix .O_CLOEXEC , 0 )
360+ if err != nil {
361+ return err
362+ }
363+
364+ cmd .ExtraFiles = append (cmd .ExtraFiles , os .NewFile (uintptr (fifoFd ), fifoName ))
365+ cmd .Env = append (cmd .Env ,
366+ fmt .Sprintf ("_LIBCONTAINER_FIFOFD=%d" , stdioFdCount + len (cmd .ExtraFiles )- 1 ))
367+ return nil
368+ }
369+
353370func (c * linuxContainer ) newParentProcess (p * Process , doInit bool ) (parentProcess , error ) {
354371 parentPipe , childPipe , err := utils .NewSockPair ("init" )
355372 if err != nil {
@@ -363,18 +380,15 @@ func (c *linuxContainer) newParentProcess(p *Process, doInit bool) (parentProces
363380 return c .newSetnsProcess (p , cmd , parentPipe , childPipe )
364381 }
365382
366- // We only set up rootDir if we're not doing a `runc exec`. The reason for
367- // this is to avoid cases where a racing, unprivileged process inside the
368- // container can get access to the statedir file descriptor (which would
369- // allow for container rootfs escape).
370- rootDir , err := os . Open ( c . root )
371- if err != nil {
372- return nil , err
383+ // We only set up fifoFd if we're not doing a `runc exec`. The historic
384+ // reason for this is that previously we would pass a dirfd that allowed
385+ // for container rootfs escape (and not doing it in `runc exec` avoided
386+ // that problem), but we no longer do that. However, there's no need to do
387+ // this for `runc exec` so we just keep it this way to be safe.
388+ if err := c . includeExecFifo ( cmd ); err != nil {
389+ return nil , newSystemErrorWithCause ( err , "including execfifo in cmd.Exec setup" )
373390 }
374- cmd .ExtraFiles = append (cmd .ExtraFiles , rootDir )
375- cmd .Env = append (cmd .Env ,
376- fmt .Sprintf ("_LIBCONTAINER_STATEDIR=%d" , stdioFdCount + len (cmd .ExtraFiles )- 1 ))
377- return c .newInitProcess (p , cmd , parentPipe , childPipe , rootDir )
391+ return c .newInitProcess (p , cmd , parentPipe , childPipe )
378392}
379393
380394func (c * linuxContainer ) commandTemplate (p * Process , childPipe * os.File ) (* exec.Cmd , error ) {
@@ -406,7 +420,7 @@ func (c *linuxContainer) commandTemplate(p *Process, childPipe *os.File) (*exec.
406420 return cmd , nil
407421}
408422
409- func (c * linuxContainer ) newInitProcess (p * Process , cmd * exec.Cmd , parentPipe , childPipe , rootDir * os.File ) (* initProcess , error ) {
423+ func (c * linuxContainer ) newInitProcess (p * Process , cmd * exec.Cmd , parentPipe , childPipe * os.File ) (* initProcess , error ) {
410424 cmd .Env = append (cmd .Env , "_LIBCONTAINER_INITTYPE=" + string (initStandard ))
411425 nsMaps := make (map [configs.NamespaceType ]string )
412426 for _ , ns := range c .config .Namespaces {
@@ -429,7 +443,6 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, parentPipe, c
429443 process : p ,
430444 bootstrapData : data ,
431445 sharePidns : sharePidns ,
432- rootDir : rootDir ,
433446 }, nil
434447}
435448
0 commit comments