github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/specconv/example.go (about) 1 package specconv 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 8 "github.com/opencontainers/runc/libcontainer/cgroups" 9 "github.com/opencontainers/runtime-spec/specs-go" 10 ) 11 12 // Example returns an example spec file, with many options set so a user can 13 // see what a standard spec file looks like. 14 func Example() *specs.Spec { 15 spec := &specs.Spec{ 16 Version: specs.Version, 17 Root: &specs.Root{ 18 Path: "rootfs", 19 Readonly: true, 20 }, 21 Process: &specs.Process{ 22 Terminal: true, 23 User: specs.User{}, 24 Args: []string{ 25 "sh", 26 }, 27 Env: []string{ 28 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 29 "TERM=xterm", 30 }, 31 Cwd: "/", 32 NoNewPrivileges: true, 33 Capabilities: &specs.LinuxCapabilities{ 34 Bounding: []string{ 35 "CAP_AUDIT_WRITE", 36 "CAP_KILL", 37 "CAP_NET_BIND_SERVICE", 38 }, 39 Permitted: []string{ 40 "CAP_AUDIT_WRITE", 41 "CAP_KILL", 42 "CAP_NET_BIND_SERVICE", 43 }, 44 Ambient: []string{ 45 "CAP_AUDIT_WRITE", 46 "CAP_KILL", 47 "CAP_NET_BIND_SERVICE", 48 }, 49 Effective: []string{ 50 "CAP_AUDIT_WRITE", 51 "CAP_KILL", 52 "CAP_NET_BIND_SERVICE", 53 }, 54 }, 55 Rlimits: []specs.POSIXRlimit{ 56 { 57 Type: "RLIMIT_NOFILE", 58 Hard: uint64(1024), 59 Soft: uint64(1024), 60 }, 61 }, 62 }, 63 Hostname: "runc", 64 Mounts: []specs.Mount{ 65 { 66 Destination: "/proc", 67 Type: "proc", 68 Source: "proc", 69 Options: nil, 70 }, 71 { 72 Destination: "/dev", 73 Type: "tmpfs", 74 Source: "tmpfs", 75 Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"}, 76 }, 77 { 78 Destination: "/dev/pts", 79 Type: "devpts", 80 Source: "devpts", 81 Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"}, 82 }, 83 { 84 Destination: "/dev/shm", 85 Type: "tmpfs", 86 Source: "shm", 87 Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"}, 88 }, 89 { 90 Destination: "/dev/mqueue", 91 Type: "mqueue", 92 Source: "mqueue", 93 Options: []string{"nosuid", "noexec", "nodev"}, 94 }, 95 { 96 Destination: "/sys", 97 Type: "sysfs", 98 Source: "sysfs", 99 Options: []string{"nosuid", "noexec", "nodev", "ro"}, 100 }, 101 { 102 Destination: "/sys/fs/cgroup", 103 Type: "cgroup", 104 Source: "cgroup", 105 Options: []string{"nosuid", "noexec", "nodev", "relatime", "ro"}, 106 }, 107 }, 108 Linux: &specs.Linux{ 109 MaskedPaths: []string{ 110 "/proc/acpi", 111 "/proc/asound", 112 "/proc/kcore", 113 "/proc/keys", 114 "/proc/latency_stats", 115 "/proc/timer_list", 116 "/proc/timer_stats", 117 "/proc/sched_debug", 118 "/sys/firmware", 119 "/proc/scsi", 120 }, 121 ReadonlyPaths: []string{ 122 "/proc/bus", 123 "/proc/fs", 124 "/proc/irq", 125 "/proc/sys", 126 "/proc/sysrq-trigger", 127 }, 128 Resources: &specs.LinuxResources{ 129 Devices: []specs.LinuxDeviceCgroup{ 130 { 131 Allow: false, 132 Access: "rwm", 133 }, 134 }, 135 }, 136 Namespaces: []specs.LinuxNamespace{ 137 { 138 Type: specs.PIDNamespace, 139 }, 140 { 141 Type: specs.NetworkNamespace, 142 }, 143 { 144 Type: specs.IPCNamespace, 145 }, 146 { 147 Type: specs.UTSNamespace, 148 }, 149 { 150 Type: specs.MountNamespace, 151 }, 152 }, 153 }, 154 } 155 if cgroups.IsCgroup2UnifiedMode() { 156 spec.Linux.Namespaces = append(spec.Linux.Namespaces, specs.LinuxNamespace{ 157 Type: specs.CgroupNamespace, 158 }) 159 } 160 return spec 161 } 162 163 // ToRootless converts the given spec file into one that should work with 164 // rootless containers (euid != 0), by removing incompatible options and adding others that 165 // are needed. 166 func ToRootless(spec *specs.Spec) { 167 var namespaces []specs.LinuxNamespace 168 169 // Remove networkns from the spec. 170 for _, ns := range spec.Linux.Namespaces { 171 switch ns.Type { 172 case specs.NetworkNamespace, specs.UserNamespace: 173 // Do nothing. 174 default: 175 namespaces = append(namespaces, ns) 176 } 177 } 178 // Add userns to the spec. 179 namespaces = append(namespaces, specs.LinuxNamespace{ 180 Type: specs.UserNamespace, 181 }) 182 spec.Linux.Namespaces = namespaces 183 184 // Add mappings for the current user. 185 spec.Linux.UIDMappings = []specs.LinuxIDMapping{{ 186 HostID: uint32(os.Geteuid()), 187 ContainerID: 0, 188 Size: 1, 189 }} 190 spec.Linux.GIDMappings = []specs.LinuxIDMapping{{ 191 HostID: uint32(os.Getegid()), 192 ContainerID: 0, 193 Size: 1, 194 }} 195 196 // Fix up mounts. 197 var mounts []specs.Mount 198 for _, mount := range spec.Mounts { 199 // Replace the /sys mount with an rbind. 200 if filepath.Clean(mount.Destination) == "/sys" { 201 mounts = append(mounts, specs.Mount{ 202 Source: "/sys", 203 Destination: "/sys", 204 Type: "none", 205 Options: []string{"rbind", "nosuid", "noexec", "nodev", "ro"}, 206 }) 207 continue 208 } 209 210 // Remove all gid= and uid= mappings. 211 var options []string 212 for _, option := range mount.Options { 213 if !strings.HasPrefix(option, "gid=") && !strings.HasPrefix(option, "uid=") { 214 options = append(options, option) 215 } 216 } 217 218 mount.Options = options 219 mounts = append(mounts, mount) 220 } 221 spec.Mounts = mounts 222 223 // Remove cgroup settings. 224 spec.Linux.Resources = nil 225 }