diff options
Diffstat (limited to 'container')
| -rw-r--r-- | container/container.go | 42 | ||||
| -rw-r--r-- | container/params.go | 11 | ||||
| -rw-r--r-- | container/params_test.go | 72 |
3 files changed, 27 insertions, 98 deletions
diff --git a/container/container.go b/container/container.go index 480452cd..d45d7a97 100644 --- a/container/container.go +++ b/container/container.go @@ -53,7 +53,7 @@ type ( ExtraFiles []*os.File // Write end of a pipe connected to the init to deliver [Params]. - setup *os.File + setup [2]*os.File // Cancels the context passed to the underlying cmd. cancel context.CancelFunc // Closed after Wait returns. Keeps the spawning thread alive. @@ -287,14 +287,16 @@ func (p *Container) Start() error { } // place setup pipe before user supplied extra files, this is later restored by init - if fd, f, err := Setup(&p.cmd.ExtraFiles); err != nil { + if r, w, err := os.Pipe(); err != nil { return &StartError{ Fatal: true, Step: "set up params stream", Err: err, } } else { - p.setup = f + fd := 3 + len(p.cmd.ExtraFiles) + p.cmd.ExtraFiles = append(p.cmd.ExtraFiles, r) + p.setup[0], p.setup[1] = r, w p.cmd.Env = []string{setupEnv + "=" + strconv.Itoa(fd)} } p.cmd.ExtraFiles = append(p.cmd.ExtraFiles, p.ExtraFiles...) @@ -428,14 +430,30 @@ func (p *Container) Start() error { // Serve serves [Container.Params] to the container init. // // Serve must only be called once. -func (p *Container) Serve() error { - if p.setup == nil { +func (p *Container) Serve() (err error) { + if p.setup[0] == nil || p.setup[1] == nil { panic("invalid serve") } + defer func() { + if closeErr := p.setup[1].Close(); err == nil { + err = closeErr + } + + if err != nil { + p.cancel() + } + p.setup[0], p.setup[1] = nil, nil + }() + if err = p.setup[0].Close(); err != nil { + return &StartError{ + Fatal: true, + Step: "close read end of init pipe", + Err: err, + Passthrough: true, + } + } - setup := p.setup - p.setup = nil - if err := setup.SetDeadline(time.Now().Add(initSetupTimeout)); err != nil { + if err = p.setup[1].SetDeadline(time.Now().Add(initSetupTimeout)); err != nil { return &StartError{ Fatal: true, Step: "set init pipe deadline", @@ -445,7 +463,6 @@ func (p *Container) Serve() error { } if p.Path == nil { - p.cancel() return &StartError{ Step: "invalid executable pathname", Err: EINVAL, @@ -461,18 +478,13 @@ func (p *Container) Serve() error { p.SeccompRules = make([]std.NativeRule, 0) } - err := gob.NewEncoder(setup).Encode(&initParams{ + return gob.NewEncoder(p.setup[1]).Encode(&initParams{ p.Params, Getuid(), Getgid(), len(p.ExtraFiles), p.msg.IsVerbose(), }) - _ = setup.Close() - if err != nil { - p.cancel() - } - return err } // Wait blocks until the container init process to exit and releases any diff --git a/container/params.go b/container/params.go index 46c3b9b2..e6cd26f8 100644 --- a/container/params.go +++ b/container/params.go @@ -8,17 +8,6 @@ import ( "syscall" ) -// Setup appends the read end of a pipe for setup params transmission and returns its fd. -func Setup(extraFiles *[]*os.File) (int, *os.File, error) { - if r, w, err := os.Pipe(); err != nil { - return -1, nil, err - } else { - fd := 3 + len(*extraFiles) - *extraFiles = append(*extraFiles, r) - return fd, w, nil - } -} - var ( ErrReceiveEnv = errors.New("environment variable not set") ) diff --git a/container/params_test.go b/container/params_test.go index 11d08850..4d2f84f6 100644 --- a/container/params_test.go +++ b/container/params_test.go @@ -1,10 +1,8 @@ package container_test import ( - "encoding/gob" "errors" "os" - "slices" "strconv" "syscall" "testing" @@ -52,74 +50,4 @@ func TestSetupReceive(t *testing.T) { t.Errorf("Receive: error = %v, want %v", err, syscall.EDOM) } }) - - t.Run("setup receive", func(t *testing.T) { - check := func(t *testing.T, useNilFdp bool) { - const key = "TEST_SETUP_RECEIVE" - payload := []uint64{syscall.MS_MGC_VAL, syscall.MS_MGC_MSK, syscall.MS_ASYNC, syscall.MS_ACTIVE} - - encoderDone := make(chan error, 1) - extraFiles := make([]*os.File, 0, 1) - deadline, _ := t.Deadline() - if fd, f, err := container.Setup(&extraFiles); err != nil { - t.Fatalf("Setup: error = %v", err) - } else if fd != 3 { - t.Fatalf("Setup: fd = %d, want 3", fd) - } else { - if err = f.SetDeadline(deadline); err != nil { - t.Fatal(err.Error()) - } - go func() { encoderDone <- gob.NewEncoder(f).Encode(payload) }() - } - - if len(extraFiles) != 1 { - t.Fatalf("extraFiles: len = %v, want 1", len(extraFiles)) - } - - var dupFd int - if fd, err := syscall.Dup(int(extraFiles[0].Fd())); err != nil { - t.Fatalf("Dup: error = %v", err) - } else { - syscall.CloseOnExec(fd) - dupFd = fd - t.Setenv(key, strconv.Itoa(fd)) - } - - var ( - gotPayload []uint64 - fdp *uintptr - ) - if !useNilFdp { - fdp = new(uintptr) - } - var closeFile func() error - if f, err := container.Receive(key, &gotPayload, fdp); err != nil { - t.Fatalf("Receive: error = %v", err) - } else { - closeFile = f - - if !slices.Equal(payload, gotPayload) { - t.Errorf("Receive: %#v, want %#v", gotPayload, payload) - } - } - if !useNilFdp { - if int(*fdp) != dupFd { - t.Errorf("Fd: %d, want %d", *fdp, dupFd) - } - } - - if err := <-encoderDone; err != nil { - t.Errorf("Encode: error = %v", err) - } - - if closeFile != nil { - if err := closeFile(); err != nil { - t.Errorf("Close: error = %v", err) - } - } - } - - t.Run("fp", func(t *testing.T) { check(t, false) }) - t.Run("nil", func(t *testing.T) { check(t, true) }) - }) } |
