| /* |
| Copyright 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 v2 |
| |
| import ( |
| "encoding/json" |
| "os" |
| |
| "github.com/opencontainers/runtime-spec/specs-go" |
| ) |
| |
| // prepareBundleDirectoryPermissions prepares the permissions of the bundle |
| // directory according to the needs of the current platform. |
| // On Linux when user namespaces are enabled, the permissions are modified to |
| // allow the remapped root GID to access the bundle. |
| func prepareBundleDirectoryPermissions(path string, spec []byte) error { |
| gid, err := remappedGID(spec) |
| if err != nil { |
| return err |
| } |
| if gid == 0 { |
| return nil |
| } |
| if err := os.Chown(path, -1, int(gid)); err != nil { |
| return err |
| } |
| return os.Chmod(path, 0710) |
| } |
| |
| // ociSpecUserNS is a subset of specs.Spec used to reduce garbage during |
| // unmarshal. |
| type ociSpecUserNS struct { |
| Linux *linuxSpecUserNS |
| } |
| |
| // linuxSpecUserNS is a subset of specs.Linux used to reduce garbage during |
| // unmarshal. |
| type linuxSpecUserNS struct { |
| GIDMappings []specs.LinuxIDMapping |
| } |
| |
| // remappedGID reads the remapped GID 0 from the OCI spec, if it exists. If |
| // there is no remapping, remappedGID returns 0. If the spec cannot be parsed, |
| // remappedGID returns an error. |
| func remappedGID(spec []byte) (uint32, error) { |
| var ociSpec ociSpecUserNS |
| err := json.Unmarshal(spec, &ociSpec) |
| if err != nil { |
| return 0, err |
| } |
| if ociSpec.Linux == nil || len(ociSpec.Linux.GIDMappings) == 0 { |
| return 0, nil |
| } |
| for _, mapping := range ociSpec.Linux.GIDMappings { |
| if mapping.ContainerID == 0 { |
| return mapping.HostID, nil |
| } |
| } |
| return 0, nil |
| } |