merge branch 'pr-1812'
Fix race in runc exec LGTMs: @dqminh @cyphar Closes #1812
This commit is contained in:
commit
dd56ece823
1
exec.go
1
exec.go
|
@ -140,6 +140,7 @@ func execProcess(context *cli.Context) (int, error) {
|
|||
detach: detach,
|
||||
pidFile: context.String("pid-file"),
|
||||
action: CT_ACT_RUN,
|
||||
init: false,
|
||||
}
|
||||
return r.run(p)
|
||||
}
|
||||
|
|
|
@ -224,17 +224,13 @@ func (c *linuxContainer) Set(config configs.Config) error {
|
|||
func (c *linuxContainer) Start(process *Process) error {
|
||||
c.m.Lock()
|
||||
defer c.m.Unlock()
|
||||
status, err := c.currentStatus()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if status == Stopped {
|
||||
if process.Init {
|
||||
if err := c.createExecFifo(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := c.start(process, status == Stopped); err != nil {
|
||||
if status == Stopped {
|
||||
if err := c.start(process); err != nil {
|
||||
if process.Init {
|
||||
c.deleteExecFifo()
|
||||
}
|
||||
return err
|
||||
|
@ -243,17 +239,10 @@ func (c *linuxContainer) Start(process *Process) error {
|
|||
}
|
||||
|
||||
func (c *linuxContainer) Run(process *Process) error {
|
||||
c.m.Lock()
|
||||
status, err := c.currentStatus()
|
||||
if err != nil {
|
||||
c.m.Unlock()
|
||||
return err
|
||||
}
|
||||
c.m.Unlock()
|
||||
if err := c.Start(process); err != nil {
|
||||
return err
|
||||
}
|
||||
if status == Stopped {
|
||||
if process.Init {
|
||||
return c.exec()
|
||||
}
|
||||
return nil
|
||||
|
@ -334,8 +323,8 @@ type openResult struct {
|
|||
err error
|
||||
}
|
||||
|
||||
func (c *linuxContainer) start(process *Process, isInit bool) error {
|
||||
parent, err := c.newParentProcess(process, isInit)
|
||||
func (c *linuxContainer) start(process *Process) error {
|
||||
parent, err := c.newParentProcess(process)
|
||||
if err != nil {
|
||||
return newSystemErrorWithCause(err, "creating new parent process")
|
||||
}
|
||||
|
@ -348,7 +337,7 @@ func (c *linuxContainer) start(process *Process, isInit bool) error {
|
|||
}
|
||||
// generate a timestamp indicating when the container was started
|
||||
c.created = time.Now().UTC()
|
||||
if isInit {
|
||||
if process.Init {
|
||||
c.state = &createdState{
|
||||
c: c,
|
||||
}
|
||||
|
@ -438,7 +427,7 @@ func (c *linuxContainer) includeExecFifo(cmd *exec.Cmd) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *linuxContainer) newParentProcess(p *Process, doInit bool) (parentProcess, error) {
|
||||
func (c *linuxContainer) newParentProcess(p *Process) (parentProcess, error) {
|
||||
parentPipe, childPipe, err := utils.NewSockPair("init")
|
||||
if err != nil {
|
||||
return nil, newSystemErrorWithCause(err, "creating new init pipe")
|
||||
|
@ -447,7 +436,7 @@ func (c *linuxContainer) newParentProcess(p *Process, doInit bool) (parentProces
|
|||
if err != nil {
|
||||
return nil, newSystemErrorWithCause(err, "creating new command template")
|
||||
}
|
||||
if !doInit {
|
||||
if !p.Init {
|
||||
return c.newSetnsProcess(p, cmd, parentPipe, childPipe)
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ func testCheckpoint(t *testing.T, userns bool) {
|
|||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Run(&pconfig)
|
||||
|
@ -205,6 +206,7 @@ func testCheckpoint(t *testing.T, userns bool) {
|
|||
Cwd: "/",
|
||||
Stdin: restoreStdinR,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Restore(restoreProcessConfig, checkpointOpts)
|
||||
|
|
|
@ -231,6 +231,7 @@ func TestEnter(t *testing.T) {
|
|||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
stdinR.Close()
|
||||
|
@ -320,6 +321,7 @@ func TestProcessEnv(t *testing.T) {
|
|||
},
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
ok(t, err)
|
||||
|
@ -366,6 +368,7 @@ func TestProcessEmptyCaps(t *testing.T) {
|
|||
Env: standardEnvironment,
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
ok(t, err)
|
||||
|
@ -417,6 +420,7 @@ func TestProcessCaps(t *testing.T) {
|
|||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Capabilities: &configs.Capabilities{},
|
||||
Init: true,
|
||||
}
|
||||
pconfig.Capabilities.Bounding = append(config.Capabilities.Bounding, "CAP_NET_ADMIN")
|
||||
pconfig.Capabilities.Permitted = append(config.Capabilities.Permitted, "CAP_NET_ADMIN")
|
||||
|
@ -491,6 +495,7 @@ func TestAdditionalGroups(t *testing.T) {
|
|||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
AdditionalGroups: []string{"plugdev", "audio"},
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
ok(t, err)
|
||||
|
@ -551,6 +556,7 @@ func testFreeze(t *testing.T, systemd bool) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(pconfig)
|
||||
stdinR.Close()
|
||||
|
@ -762,6 +768,7 @@ func TestContainerState(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(p)
|
||||
if err != nil {
|
||||
|
@ -821,6 +828,7 @@ func TestPassExtraFiles(t *testing.T) {
|
|||
ExtraFiles: []*os.File{pipein1, pipein2},
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&process)
|
||||
if err != nil {
|
||||
|
@ -902,6 +910,7 @@ func TestMountCmds(t *testing.T) {
|
|||
Cwd: "/",
|
||||
Args: []string{"sh", "-c", "env"},
|
||||
Env: standardEnvironment,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
if err != nil {
|
||||
|
@ -951,6 +960,7 @@ func TestSysctl(t *testing.T) {
|
|||
Env: standardEnvironment,
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
ok(t, err)
|
||||
|
@ -1091,6 +1101,7 @@ func TestOomScoreAdj(t *testing.T) {
|
|||
Env: standardEnvironment,
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
ok(t, err)
|
||||
|
@ -1196,6 +1207,7 @@ func TestHook(t *testing.T) {
|
|||
Env: standardEnvironment,
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
ok(t, err)
|
||||
|
@ -1312,6 +1324,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Run(pconfig)
|
||||
|
@ -1429,6 +1442,7 @@ func TestRootfsPropagationSharedMount(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Run(pconfig)
|
||||
|
@ -1537,6 +1551,7 @@ func TestInitJoinPID(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR1,
|
||||
Init: true,
|
||||
}
|
||||
err = container1.Run(init1)
|
||||
stdinR1.Close()
|
||||
|
@ -1563,6 +1578,7 @@ func TestInitJoinPID(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR2,
|
||||
Init: true,
|
||||
}
|
||||
err = container2.Run(init2)
|
||||
stdinR2.Close()
|
||||
|
@ -1642,6 +1658,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR1,
|
||||
Init: true,
|
||||
}
|
||||
err = container1.Run(init1)
|
||||
stdinR1.Close()
|
||||
|
@ -1676,6 +1693,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR2,
|
||||
Init: true,
|
||||
}
|
||||
err = container2.Run(init2)
|
||||
stdinR2.Close()
|
||||
|
@ -1743,6 +1761,7 @@ func TestTmpfsCopyUp(t *testing.T) {
|
|||
Env: standardEnvironment,
|
||||
Stdin: nil,
|
||||
Stdout: &stdout,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(&pconfig)
|
||||
ok(t, err)
|
||||
|
|
|
@ -38,6 +38,7 @@ func TestExecIn(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -108,6 +109,7 @@ func testExecInRlimit(t *testing.T, userns bool) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -126,6 +128,7 @@ func testExecInRlimit(t *testing.T, userns bool) {
|
|||
// increase process rlimit higher than container rlimit to test per-process limit
|
||||
{Type: unix.RLIMIT_NOFILE, Hard: 1026, Soft: 1026},
|
||||
},
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(ps)
|
||||
ok(t, err)
|
||||
|
@ -162,6 +165,7 @@ func TestExecInAdditionalGroups(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -218,6 +222,7 @@ func TestExecInError(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -270,6 +275,7 @@ func TestExecInTTY(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -366,6 +372,7 @@ func TestExecInEnvironment(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -385,6 +392,7 @@ func TestExecInEnvironment(t *testing.T) {
|
|||
Stdin: buffers.Stdin,
|
||||
Stdout: buffers.Stdout,
|
||||
Stderr: buffers.Stderr,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process2)
|
||||
ok(t, err)
|
||||
|
@ -430,6 +438,7 @@ func TestExecinPassExtraFiles(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -509,6 +518,7 @@ func TestExecInOomScoreAdj(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
@ -564,6 +574,7 @@ func TestExecInUserns(t *testing.T) {
|
|||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
stdinR.Close()
|
||||
|
|
|
@ -48,6 +48,7 @@ func TestSeccompDenyGetcwd(t *testing.T) {
|
|||
Stdin: buffers.Stdin,
|
||||
Stdout: buffers.Stdout,
|
||||
Stderr: buffers.Stderr,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Run(pwd)
|
||||
|
@ -123,6 +124,7 @@ func TestSeccompPermitWriteConditional(t *testing.T) {
|
|||
Stdin: buffers.Stdin,
|
||||
Stdout: buffers.Stdout,
|
||||
Stderr: buffers.Stderr,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Run(dmesg)
|
||||
|
@ -184,6 +186,7 @@ func TestSeccompDenyWriteConditional(t *testing.T) {
|
|||
Stdin: buffers.Stdin,
|
||||
Stdout: buffers.Stdout,
|
||||
Stderr: buffers.Stderr,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Run(dmesg)
|
||||
|
|
|
@ -152,6 +152,7 @@ func runContainer(config *configs.Config, console string, args ...string) (buffe
|
|||
Stdin: buffers.Stdin,
|
||||
Stdout: buffers.Stdout,
|
||||
Stderr: buffers.Stderr,
|
||||
Init: true,
|
||||
}
|
||||
|
||||
err = container.Run(process)
|
||||
|
|
|
@ -72,6 +72,9 @@ type Process struct {
|
|||
// ConsoleSocket provides the masterfd console.
|
||||
ConsoleSocket *os.File
|
||||
|
||||
// Init specifies whether the process is the first process in the container.
|
||||
Init bool
|
||||
|
||||
ops processOperations
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ func getDefaultImagePath(context *cli.Context) string {
|
|||
|
||||
// newProcess returns a new libcontainer Process with the arguments from the
|
||||
// spec and stdio from the current process.
|
||||
func newProcess(p specs.Process) (*libcontainer.Process, error) {
|
||||
func newProcess(p specs.Process, init bool) (*libcontainer.Process, error) {
|
||||
lp := &libcontainer.Process{
|
||||
Args: p.Args,
|
||||
Env: p.Env,
|
||||
|
@ -115,6 +115,7 @@ func newProcess(p specs.Process) (*libcontainer.Process, error) {
|
|||
Label: p.SelinuxLabel,
|
||||
NoNewPrivileges: &p.NoNewPrivileges,
|
||||
AppArmorProfile: p.ApparmorProfile,
|
||||
Init: init,
|
||||
}
|
||||
|
||||
if p.ConsoleSize != nil {
|
||||
|
@ -269,6 +270,7 @@ func createContainer(context *cli.Context, id string, spec *specs.Spec) (libcont
|
|||
}
|
||||
|
||||
type runner struct {
|
||||
init bool
|
||||
enableSubreaper bool
|
||||
shouldDestroy bool
|
||||
detach bool
|
||||
|
@ -287,7 +289,7 @@ func (r *runner) run(config *specs.Process) (int, error) {
|
|||
r.destroy()
|
||||
return -1, err
|
||||
}
|
||||
process, err := newProcess(*config)
|
||||
process, err := newProcess(*config, r.init)
|
||||
if err != nil {
|
||||
r.destroy()
|
||||
return -1, err
|
||||
|
@ -450,6 +452,7 @@ func startContainer(context *cli.Context, spec *specs.Spec, action CtAct, criuOp
|
|||
preserveFDs: context.Int("preserve-fds"),
|
||||
action: action,
|
||||
criuOpts: criuOpts,
|
||||
init: true,
|
||||
}
|
||||
return r.run(spec.Process)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue