Merge pull request #46221 from thaJeztah/24.0_backport_capabilites
[24.0 backport] Do not drop effective&permitted set
This commit is contained in:
commit
ad7a03eb33
4 changed files with 163 additions and 13 deletions
108
integration/capabilities/capabilities_linux_test.go
Normal file
108
integration/capabilities/capabilities_linux_test.go
Normal file
|
@ -0,0 +1,108 @@
|
|||
package capabilities
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/testutil/fakecontext"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/poll"
|
||||
)
|
||||
|
||||
func TestNoNewPrivileges(t *testing.T) {
|
||||
defer setupTest(t)()
|
||||
|
||||
withFileCapability := `
|
||||
FROM debian:bullseye-slim
|
||||
RUN apt-get update && apt-get install -y libcap2-bin --no-install-recommends
|
||||
RUN setcap CAP_DAC_OVERRIDE=+eip /bin/cat
|
||||
RUN echo "hello" > /txt && chown 0:0 /txt && chmod 700 /txt
|
||||
RUN useradd -u 1500 test
|
||||
`
|
||||
imageTag := "captest"
|
||||
|
||||
source := fakecontext.New(t, "", fakecontext.WithDockerfile(withFileCapability))
|
||||
defer source.Close()
|
||||
|
||||
client := testEnv.APIClient()
|
||||
|
||||
// Build image
|
||||
ctx := context.TODO()
|
||||
resp, err := client.ImageBuild(ctx,
|
||||
source.AsTarReader(t),
|
||||
types.ImageBuildOptions{
|
||||
Tags: []string{imageTag},
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
_, err = io.Copy(io.Discard, resp.Body)
|
||||
assert.NilError(t, err)
|
||||
resp.Body.Close()
|
||||
|
||||
testCases := []struct {
|
||||
doc string
|
||||
opts []func(*container.TestContainerConfig)
|
||||
stdOut, stdErr string
|
||||
}{
|
||||
{
|
||||
doc: "CapabilityRequested=true",
|
||||
opts: []func(*container.TestContainerConfig){
|
||||
container.WithUser("test"),
|
||||
container.WithCapability("CAP_DAC_OVERRIDE"),
|
||||
},
|
||||
stdOut: "hello",
|
||||
},
|
||||
{
|
||||
doc: "CapabilityRequested=false",
|
||||
opts: []func(*container.TestContainerConfig){
|
||||
container.WithUser("test"),
|
||||
container.WithDropCapability("CAP_DAC_OVERRIDE"),
|
||||
},
|
||||
stdErr: "exec /bin/cat: operation not permitted",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
// Run the container with the image
|
||||
opts := append(tc.opts,
|
||||
container.WithImage(imageTag),
|
||||
container.WithCmd("/bin/cat", "/txt"),
|
||||
container.WithSecurityOpt("no-new-privileges=true"),
|
||||
)
|
||||
cid := container.Run(ctx, t, client, opts...)
|
||||
poll.WaitOn(t, container.IsInState(ctx, client, cid, "exited"), poll.WithDelay(100*time.Millisecond))
|
||||
|
||||
// Assert on outputs
|
||||
logReader, err := client.ContainerLogs(ctx, cid, types.ContainerLogsOptions{
|
||||
ShowStdout: true,
|
||||
ShowStderr: true,
|
||||
})
|
||||
assert.NilError(t, err)
|
||||
defer logReader.Close()
|
||||
|
||||
var actualStdout, actualStderr bytes.Buffer
|
||||
_, err = stdcopy.StdCopy(&actualStdout, &actualStderr, logReader)
|
||||
assert.NilError(t, err)
|
||||
|
||||
stdOut := strings.TrimSpace(actualStdout.String())
|
||||
stdErr := strings.TrimSpace(actualStderr.String())
|
||||
if stdOut != tc.stdOut {
|
||||
t.Fatalf("test produced invalid output: %q, expected %q. Stderr:%q", stdOut, tc.stdOut, stdErr)
|
||||
}
|
||||
if stdErr != tc.stdErr {
|
||||
t.Fatalf("test produced invalid error: %q, expected %q. Stdout:%q", stdErr, tc.stdErr, stdOut)
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
33
integration/capabilities/main_linux_test.go
Normal file
33
integration/capabilities/main_linux_test.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package capabilities
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/testutil/environment"
|
||||
)
|
||||
|
||||
var testEnv *environment.Execution
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
var err error
|
||||
testEnv, err = environment.New()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = environment.EnsureFrozenImagesLinux(testEnv)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
testEnv.Print()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func setupTest(t *testing.T) func() {
|
||||
environment.ProtectAll(t, testEnv)
|
||||
return func() { testEnv.Clean(t) }
|
||||
}
|
|
@ -237,3 +237,21 @@ func WithRuntime(name string) func(*TestContainerConfig) {
|
|||
c.HostConfig.Runtime = name
|
||||
}
|
||||
}
|
||||
|
||||
func WithCapability(capabilities ...string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.HostConfig.CapAdd = append(c.HostConfig.CapAdd, capabilities...)
|
||||
}
|
||||
}
|
||||
|
||||
func WithDropCapability(capabilities ...string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.HostConfig.CapDrop = append(c.HostConfig.CapDrop, capabilities...)
|
||||
}
|
||||
}
|
||||
|
||||
func WithSecurityOpt(opt string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.HostConfig.SecurityOpt = append(c.HostConfig.SecurityOpt, opt)
|
||||
}
|
||||
}
|
||||
|
|
17
oci/oci.go
17
oci/oci.go
|
@ -23,19 +23,10 @@ func SetCapabilities(s *specs.Spec, caplist []string) error {
|
|||
if s.Process == nil {
|
||||
s.Process = &specs.Process{}
|
||||
}
|
||||
// setUser has already been executed here
|
||||
if s.Process.User.UID == 0 {
|
||||
s.Process.Capabilities = &specs.LinuxCapabilities{
|
||||
Effective: caplist,
|
||||
Bounding: caplist,
|
||||
Permitted: caplist,
|
||||
}
|
||||
} else {
|
||||
// Do not set Effective and Permitted capabilities for non-root users,
|
||||
// to match what execve does.
|
||||
s.Process.Capabilities = &specs.LinuxCapabilities{
|
||||
Bounding: caplist,
|
||||
}
|
||||
s.Process.Capabilities = &specs.LinuxCapabilities{
|
||||
Effective: caplist,
|
||||
Bounding: caplist,
|
||||
Permitted: caplist,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue