github.com/demonoid81/containerd@v1.3.4/oci/spec.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package oci 18 19 import ( 20 "context" 21 "path/filepath" 22 "runtime" 23 24 "github.com/containerd/containerd/namespaces" 25 "github.com/containerd/containerd/platforms" 26 27 "github.com/containerd/containerd/containers" 28 specs "github.com/opencontainers/runtime-spec/specs-go" 29 ) 30 31 const ( 32 rwm = "rwm" 33 defaultRootfsPath = "rootfs" 34 ) 35 36 var ( 37 defaultUnixEnv = []string{ 38 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 39 } 40 ) 41 42 // Spec is a type alias to the OCI runtime spec to allow third part SpecOpts 43 // to be created without the "issues" with go vendoring and package imports 44 type Spec = specs.Spec 45 46 // GenerateSpec will generate a default spec from the provided image 47 // for use as a containerd container 48 func GenerateSpec(ctx context.Context, client Client, c *containers.Container, opts ...SpecOpts) (*Spec, error) { 49 return GenerateSpecWithPlatform(ctx, client, platforms.DefaultString(), c, opts...) 50 } 51 52 // GenerateSpecWithPlatform will generate a default spec from the provided image 53 // for use as a containerd container in the platform requested. 54 func GenerateSpecWithPlatform(ctx context.Context, client Client, platform string, c *containers.Container, opts ...SpecOpts) (*Spec, error) { 55 var s Spec 56 if err := generateDefaultSpecWithPlatform(ctx, platform, c.ID, &s); err != nil { 57 return nil, err 58 } 59 60 return &s, ApplyOpts(ctx, client, c, &s, opts...) 61 } 62 63 func generateDefaultSpecWithPlatform(ctx context.Context, platform, id string, s *Spec) error { 64 plat, err := platforms.Parse(platform) 65 if err != nil { 66 return err 67 } 68 69 if plat.OS == "windows" { 70 err = populateDefaultWindowsSpec(ctx, s, id) 71 } else { 72 err = populateDefaultUnixSpec(ctx, s, id) 73 if err == nil && runtime.GOOS == "windows" { 74 // To run LCOW we have a Linux and Windows section. Add an empty one now. 75 s.Windows = &specs.Windows{} 76 } 77 } 78 return err 79 } 80 81 // ApplyOpts applies the options to the given spec, injecting data from the 82 // context, client and container instance. 83 func ApplyOpts(ctx context.Context, client Client, c *containers.Container, s *Spec, opts ...SpecOpts) error { 84 for _, o := range opts { 85 if err := o(ctx, client, c, s); err != nil { 86 return err 87 } 88 } 89 90 return nil 91 } 92 93 func defaultUnixCaps() []string { 94 return []string{ 95 "CAP_CHOWN", 96 "CAP_DAC_OVERRIDE", 97 "CAP_FSETID", 98 "CAP_FOWNER", 99 "CAP_MKNOD", 100 "CAP_NET_RAW", 101 "CAP_SETGID", 102 "CAP_SETUID", 103 "CAP_SETFCAP", 104 "CAP_SETPCAP", 105 "CAP_NET_BIND_SERVICE", 106 "CAP_SYS_CHROOT", 107 "CAP_KILL", 108 "CAP_AUDIT_WRITE", 109 } 110 } 111 112 func defaultUnixNamespaces() []specs.LinuxNamespace { 113 return []specs.LinuxNamespace{ 114 { 115 Type: specs.PIDNamespace, 116 }, 117 { 118 Type: specs.IPCNamespace, 119 }, 120 { 121 Type: specs.UTSNamespace, 122 }, 123 { 124 Type: specs.MountNamespace, 125 }, 126 { 127 Type: specs.NetworkNamespace, 128 }, 129 } 130 } 131 132 func populateDefaultUnixSpec(ctx context.Context, s *Spec, id string) error { 133 ns, err := namespaces.NamespaceRequired(ctx) 134 if err != nil { 135 return err 136 } 137 138 *s = Spec{ 139 Version: specs.Version, 140 Root: &specs.Root{ 141 Path: defaultRootfsPath, 142 }, 143 Process: &specs.Process{ 144 Cwd: "/", 145 NoNewPrivileges: true, 146 User: specs.User{ 147 UID: 0, 148 GID: 0, 149 }, 150 Capabilities: &specs.LinuxCapabilities{ 151 Bounding: defaultUnixCaps(), 152 Permitted: defaultUnixCaps(), 153 Inheritable: defaultUnixCaps(), 154 Effective: defaultUnixCaps(), 155 }, 156 Rlimits: []specs.POSIXRlimit{ 157 { 158 Type: "RLIMIT_NOFILE", 159 Hard: uint64(1024), 160 Soft: uint64(1024), 161 }, 162 }, 163 }, 164 Mounts: []specs.Mount{ 165 { 166 Destination: "/proc", 167 Type: "proc", 168 Source: "proc", 169 Options: []string{"nosuid", "noexec", "nodev"}, 170 }, 171 { 172 Destination: "/dev", 173 Type: "tmpfs", 174 Source: "tmpfs", 175 Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, 176 }, 177 { 178 Destination: "/dev/pts", 179 Type: "devpts", 180 Source: "devpts", 181 Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"}, 182 }, 183 { 184 Destination: "/dev/shm", 185 Type: "tmpfs", 186 Source: "shm", 187 Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"}, 188 }, 189 { 190 Destination: "/dev/mqueue", 191 Type: "mqueue", 192 Source: "mqueue", 193 Options: []string{"nosuid", "noexec", "nodev"}, 194 }, 195 { 196 Destination: "/sys", 197 Type: "sysfs", 198 Source: "sysfs", 199 Options: []string{"nosuid", "noexec", "nodev", "ro"}, 200 }, 201 { 202 Destination: "/run", 203 Type: "tmpfs", 204 Source: "tmpfs", 205 Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, 206 }, 207 }, 208 Linux: &specs.Linux{ 209 MaskedPaths: []string{ 210 "/proc/acpi", 211 "/proc/asound", 212 "/proc/kcore", 213 "/proc/keys", 214 "/proc/latency_stats", 215 "/proc/timer_list", 216 "/proc/timer_stats", 217 "/proc/sched_debug", 218 "/sys/firmware", 219 "/proc/scsi", 220 }, 221 ReadonlyPaths: []string{ 222 "/proc/bus", 223 "/proc/fs", 224 "/proc/irq", 225 "/proc/sys", 226 "/proc/sysrq-trigger", 227 }, 228 CgroupsPath: filepath.Join("/", ns, id), 229 Resources: &specs.LinuxResources{ 230 Devices: []specs.LinuxDeviceCgroup{ 231 { 232 Allow: false, 233 Access: rwm, 234 }, 235 }, 236 }, 237 Namespaces: defaultUnixNamespaces(), 238 }, 239 } 240 return nil 241 } 242 243 func populateDefaultWindowsSpec(ctx context.Context, s *Spec, id string) error { 244 *s = Spec{ 245 Version: specs.Version, 246 Root: &specs.Root{}, 247 Process: &specs.Process{ 248 Cwd: `C:\`, 249 }, 250 Windows: &specs.Windows{}, 251 } 252 return nil 253 }