github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/runc/libcontainer/configs/config.go (about) 1 package configs 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "os/exec" 8 "time" 9 10 "github.com/Sirupsen/logrus" 11 ) 12 13 type Rlimit struct { 14 Type int `json:"type"` 15 Hard uint64 `json:"hard"` 16 Soft uint64 `json:"soft"` 17 } 18 19 // IDMap represents UID/GID Mappings for User Namespaces. 20 type IDMap struct { 21 ContainerID int `json:"container_id"` 22 HostID int `json:"host_id"` 23 Size int `json:"size"` 24 } 25 26 // Seccomp represents syscall restrictions 27 // By default, only the native architecture of the kernel is allowed to be used 28 // for syscalls. Additional architectures can be added by specifying them in 29 // Architectures. 30 type Seccomp struct { 31 DefaultAction Action `json:"default_action"` 32 Architectures []string `json:"architectures"` 33 Syscalls []*Syscall `json:"syscalls"` 34 } 35 36 // Action is taken upon rule match in Seccomp 37 type Action int 38 39 const ( 40 Kill Action = iota + 1 41 Errno 42 Trap 43 Allow 44 Trace 45 ) 46 47 // Operator is a comparison operator to be used when matching syscall arguments in Seccomp 48 type Operator int 49 50 const ( 51 EqualTo Operator = iota + 1 52 NotEqualTo 53 GreaterThan 54 GreaterThanOrEqualTo 55 LessThan 56 LessThanOrEqualTo 57 MaskEqualTo 58 ) 59 60 // Arg is a rule to match a specific syscall argument in Seccomp 61 type Arg struct { 62 Index uint `json:"index"` 63 Value uint64 `json:"value"` 64 ValueTwo uint64 `json:"value_two"` 65 Op Operator `json:"op"` 66 } 67 68 // Syscall is a rule to match a syscall in Seccomp 69 type Syscall struct { 70 Name string `json:"name"` 71 Action Action `json:"action"` 72 Args []*Arg `json:"args"` 73 } 74 75 // TODO Windows. Many of these fields should be factored out into those parts 76 // which are common across platforms, and those which are platform specific. 77 78 // Config defines configuration options for executing a process inside a contained environment. 79 type Config struct { 80 // NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs 81 // This is a common option when the container is running in ramdisk 82 NoPivotRoot bool `json:"no_pivot_root"` 83 84 // ParentDeathSignal specifies the signal that is sent to the container's process in the case 85 // that the parent process dies. 86 ParentDeathSignal int `json:"parent_death_signal"` 87 88 // Path to a directory containing the container's root filesystem. 89 Rootfs string `json:"rootfs"` 90 91 // Readonlyfs will remount the container's rootfs as readonly where only externally mounted 92 // bind mounts are writtable. 93 Readonlyfs bool `json:"readonlyfs"` 94 95 // Specifies the mount propagation flags to be applied to /. 96 RootPropagation int `json:"rootPropagation"` 97 98 // Mounts specify additional source and destination paths that will be mounted inside the container's 99 // rootfs and mount namespace if specified 100 Mounts []*Mount `json:"mounts"` 101 102 // The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well! 103 Devices []*Device `json:"devices"` 104 105 MountLabel string `json:"mount_label"` 106 107 // Hostname optionally sets the container's hostname if provided 108 Hostname string `json:"hostname"` 109 110 // Namespaces specifies the container's namespaces that it should setup when cloning the init process 111 // If a namespace is not provided that namespace is shared from the container's parent process 112 Namespaces Namespaces `json:"namespaces"` 113 114 // Capabilities specify the capabilities to keep when executing the process inside the container 115 // All capbilities not specified will be dropped from the processes capability mask 116 Capabilities []string `json:"capabilities"` 117 118 // Networks specifies the container's network setup to be created 119 Networks []*Network `json:"networks"` 120 121 // Routes can be specified to create entries in the route table as the container is started 122 Routes []*Route `json:"routes"` 123 124 // Cgroups specifies specific cgroup settings for the various subsystems that the container is 125 // placed into to limit the resources the container has available 126 Cgroups *Cgroup `json:"cgroups"` 127 128 // AppArmorProfile specifies the profile to apply to the process running in the container and is 129 // change at the time the process is execed 130 AppArmorProfile string `json:"apparmor_profile,omitempty"` 131 132 // ProcessLabel specifies the label to apply to the process running in the container. It is 133 // commonly used by selinux 134 ProcessLabel string `json:"process_label,omitempty"` 135 136 // Rlimits specifies the resource limits, such as max open files, to set in the container 137 // If Rlimits are not set, the container will inherit rlimits from the parent process 138 Rlimits []Rlimit `json:"rlimits,omitempty"` 139 140 // OomScoreAdj specifies the adjustment to be made by the kernel when calculating oom scores 141 // for a process. Valid values are between the range [-1000, '1000'], where processes with 142 // higher scores are preferred for being killed. 143 // More information about kernel oom score calculation here: https://lwn.net/Articles/317814/ 144 OomScoreAdj int `json:"oom_score_adj"` 145 146 // UidMappings is an array of User ID mappings for User Namespaces 147 UidMappings []IDMap `json:"uid_mappings"` 148 149 // GidMappings is an array of Group ID mappings for User Namespaces 150 GidMappings []IDMap `json:"gid_mappings"` 151 152 // MaskPaths specifies paths within the container's rootfs to mask over with a bind 153 // mount pointing to /dev/null as to prevent reads of the file. 154 MaskPaths []string `json:"mask_paths"` 155 156 // ReadonlyPaths specifies paths within the container's rootfs to remount as read-only 157 // so that these files prevent any writes. 158 ReadonlyPaths []string `json:"readonly_paths"` 159 160 // Sysctl is a map of properties and their values. It is the equivalent of using 161 // sysctl -w my.property.name value in Linux. 162 Sysctl map[string]string `json:"sysctl"` 163 164 // Seccomp allows actions to be taken whenever a syscall is made within the container. 165 // A number of rules are given, each having an action to be taken if a syscall matches it. 166 // A default action to be taken if no rules match is also given. 167 Seccomp *Seccomp `json:"seccomp"` 168 169 // NoNewPrivileges controls whether processes in the container can gain additional privileges. 170 NoNewPrivileges bool `json:"no_new_privileges,omitempty"` 171 172 // Hooks are a collection of actions to perform at various container lifecycle events. 173 // CommandHooks are serialized to JSON, but other hooks are not. 174 Hooks *Hooks 175 176 // Version is the version of opencontainer specification that is supported. 177 Version string `json:"version"` 178 179 // Labels are user defined metadata that is stored in the config and populated on the state 180 Labels []string `json:"labels"` 181 182 // NoNewKeyring will not allocated a new session keyring for the container. It will use the 183 // callers keyring in this case. 184 NoNewKeyring bool `json:"no_new_keyring"` 185 } 186 187 type Hooks struct { 188 // Prestart commands are executed after the container namespaces are created, 189 // but before the user supplied command is executed from init. 190 Prestart []Hook 191 192 // Poststart commands are executed after the container init process starts. 193 Poststart []Hook 194 195 // Poststop commands are executed after the container init process exits. 196 Poststop []Hook 197 } 198 199 func (hooks *Hooks) UnmarshalJSON(b []byte) error { 200 var state struct { 201 Prestart []CommandHook 202 Poststart []CommandHook 203 Poststop []CommandHook 204 } 205 206 if err := json.Unmarshal(b, &state); err != nil { 207 return err 208 } 209 210 deserialize := func(shooks []CommandHook) (hooks []Hook) { 211 for _, shook := range shooks { 212 hooks = append(hooks, shook) 213 } 214 215 return hooks 216 } 217 218 hooks.Prestart = deserialize(state.Prestart) 219 hooks.Poststart = deserialize(state.Poststart) 220 hooks.Poststop = deserialize(state.Poststop) 221 return nil 222 } 223 224 func (hooks Hooks) MarshalJSON() ([]byte, error) { 225 serialize := func(hooks []Hook) (serializableHooks []CommandHook) { 226 for _, hook := range hooks { 227 switch chook := hook.(type) { 228 case CommandHook: 229 serializableHooks = append(serializableHooks, chook) 230 default: 231 logrus.Warnf("cannot serialize hook of type %T, skipping", hook) 232 } 233 } 234 235 return serializableHooks 236 } 237 238 return json.Marshal(map[string]interface{}{ 239 "prestart": serialize(hooks.Prestart), 240 "poststart": serialize(hooks.Poststart), 241 "poststop": serialize(hooks.Poststop), 242 }) 243 } 244 245 // HookState is the payload provided to a hook on execution. 246 type HookState struct { 247 Version string `json:"ociVersion"` 248 ID string `json:"id"` 249 Pid int `json:"pid"` 250 Root string `json:"root"` 251 BundlePath string `json:"bundlePath"` 252 } 253 254 type Hook interface { 255 // Run executes the hook with the provided state. 256 Run(HookState) error 257 } 258 259 // NewFunctionHook will call the provided function when the hook is run. 260 func NewFunctionHook(f func(HookState) error) FuncHook { 261 return FuncHook{ 262 run: f, 263 } 264 } 265 266 type FuncHook struct { 267 run func(HookState) error 268 } 269 270 func (f FuncHook) Run(s HookState) error { 271 return f.run(s) 272 } 273 274 type Command struct { 275 Path string `json:"path"` 276 Args []string `json:"args"` 277 Env []string `json:"env"` 278 Dir string `json:"dir"` 279 Timeout *time.Duration `json:"timeout"` 280 } 281 282 // NewCommandHook will execute the provided command when the hook is run. 283 func NewCommandHook(cmd Command) CommandHook { 284 return CommandHook{ 285 Command: cmd, 286 } 287 } 288 289 type CommandHook struct { 290 Command 291 } 292 293 func (c Command) Run(s HookState) error { 294 b, err := json.Marshal(s) 295 if err != nil { 296 return err 297 } 298 var stdout, stderr bytes.Buffer 299 cmd := exec.Cmd{ 300 Path: c.Path, 301 Args: c.Args, 302 Env: c.Env, 303 Stdin: bytes.NewReader(b), 304 Stdout: &stdout, 305 Stderr: &stderr, 306 } 307 if err := cmd.Start(); err != nil { 308 return err 309 } 310 errC := make(chan error, 1) 311 go func() { 312 err := cmd.Wait() 313 if err != nil { 314 err = fmt.Errorf("error running hook: %v, stdout: %s, stderr: %s", err, stdout.String(), stderr.String()) 315 } 316 errC <- err 317 }() 318 var timerCh <-chan time.Time 319 if c.Timeout != nil { 320 timer := time.NewTimer(*c.Timeout) 321 defer timer.Stop() 322 timerCh = timer.C 323 } 324 select { 325 case err := <-errC: 326 return err 327 case <-timerCh: 328 cmd.Process.Kill() 329 cmd.Wait() 330 return fmt.Errorf("hook ran past specified timeout of %.1fs", c.Timeout.Seconds()) 331 } 332 }