From ca3b806b5cb960e3d2de034434fe65ac7bc43793 Mon Sep 17 00:00:00 2001 From: Lantao Liu Date: Wed, 12 Sep 2018 14:39:36 -0700 Subject: [PATCH] Fix addition group ids. Signed-off-by: Lantao Liu --- pkg/containerd/opts/spec.go | 51 ++++++++++++++++++++++++++++++++ pkg/containerd/opts/spec_test.go | 29 ++++++++++++++++++ pkg/server/container_create.go | 9 ++++++ 3 files changed, 89 insertions(+) create mode 100644 pkg/containerd/opts/spec.go create mode 100644 pkg/containerd/opts/spec_test.go diff --git a/pkg/containerd/opts/spec.go b/pkg/containerd/opts/spec.go new file mode 100644 index 000000000..3ac100139 --- /dev/null +++ b/pkg/containerd/opts/spec.go @@ -0,0 +1,51 @@ +/* +Copyright 2018 The containerd Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package opts + +import ( + "context" + + "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/oci" + runtimespec "github.com/opencontainers/runtime-spec/specs-go" +) + +// WithAdditionalGIDs adds any additional groups listed for a particular user in the +// /etc/groups file of the image's root filesystem to the OCI spec's additionalGids array. +func WithAdditionalGIDs(userstr string) oci.SpecOpts { + return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) { + gids := s.Process.User.AdditionalGids + if err := oci.WithAdditionalGIDs(userstr)(ctx, client, c, s); err != nil { + return err + } + // Merge existing gids and new gids. + s.Process.User.AdditionalGids = mergeGids(s.Process.User.AdditionalGids, gids) + return nil + } +} + +func mergeGids(gids1, gids2 []uint32) []uint32 { + for _, gid1 := range gids1 { + for i, gid2 := range gids2 { + if gid1 == gid2 { + gids2 = append(gids2[:i], gids2[i+1:]...) + break + } + } + } + return append(gids1, gids2...) +} diff --git a/pkg/containerd/opts/spec_test.go b/pkg/containerd/opts/spec_test.go new file mode 100644 index 000000000..ccfdda257 --- /dev/null +++ b/pkg/containerd/opts/spec_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2018 The containerd Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package opts + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMergeGids(t *testing.T) { + gids1 := []uint32{3, 2, 1} + gids2 := []uint32{2, 3, 4} + assert.Equal(t, []uint32{3, 2, 1, 4}, mergeGids(gids1, gids2)) +} diff --git a/pkg/server/container_create.go b/pkg/server/container_create.go index ecd57e1b9..5911c9075 100644 --- a/pkg/server/container_create.go +++ b/pkg/server/container_create.go @@ -229,6 +229,15 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta specOpts = append(specOpts, oci.WithUser(userstr)) } + if securityContext.GetRunAsUsername() != "" { + userstr = securityContext.GetRunAsUsername() + } else { + // Even if RunAsUser is not set, we still call `GetValue` to get uid 0. + // Because it is still useful to get additional gids for uid 0. + userstr = strconv.FormatInt(securityContext.GetRunAsUser().GetValue(), 10) + } + specOpts = append(specOpts, customopts.WithAdditionalGIDs(userstr)) + apparmorSpecOpts, err := generateApparmorSpecOpts( securityContext.GetApparmorProfile(), securityContext.GetPrivileged(),