github.com/containers/podman/v4@v4.9.4/pkg/namespaces/namespaces.go (about) 1 package namespaces 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "github.com/containers/storage/types" 9 ) 10 11 const ( 12 bridgeType = "bridge" 13 containerType = "container" 14 defaultType = "default" 15 hostType = "host" 16 noneType = "none" 17 nsType = "ns" 18 podType = "pod" 19 privateType = "private" 20 shareableType = "shareable" 21 slirpType = "slirp4netns" 22 pastaType = "pasta" 23 ) 24 25 // KeepIDUserNsOptions defines how to keepIDmatically create a user namespace. 26 type KeepIDUserNsOptions struct { 27 // UID is the target uid in the user namespace. 28 UID *uint32 29 // GID is the target uid in the user namespace. 30 GID *uint32 31 } 32 33 // CgroupMode represents cgroup mode in the container. 34 type CgroupMode string 35 36 // IsHost indicates whether the container uses the host's cgroup. 37 func (n CgroupMode) IsHost() bool { 38 return n == hostType 39 } 40 41 // IsDefaultValue indicates whether the cgroup namespace has the default value. 42 func (n CgroupMode) IsDefaultValue() bool { 43 return n == "" || n == defaultType 44 } 45 46 // IsNS indicates a cgroup namespace passed in by path (ns:<path>) 47 func (n CgroupMode) IsNS() bool { 48 return strings.HasPrefix(string(n), nsType) 49 } 50 51 // NS gets the path associated with a ns:<path> cgroup ns 52 func (n CgroupMode) NS() string { 53 parts := strings.SplitN(string(n), ":", 2) 54 if len(parts) > 1 { 55 return parts[1] 56 } 57 return "" 58 } 59 60 // IsContainer indicates whether the container uses a new cgroup namespace. 61 func (n CgroupMode) IsContainer() bool { 62 parts := strings.SplitN(string(n), ":", 2) 63 return len(parts) > 1 && parts[0] == containerType 64 } 65 66 // Container returns the name of the container whose cgroup namespace is going to be used. 67 func (n CgroupMode) Container() string { 68 parts := strings.SplitN(string(n), ":", 2) 69 if len(parts) > 1 && parts[0] == containerType { 70 return parts[1] 71 } 72 return "" 73 } 74 75 // IsPrivate indicates whether the container uses the a private cgroup. 76 func (n CgroupMode) IsPrivate() bool { 77 return n == privateType 78 } 79 80 // Valid indicates whether the Cgroup namespace is valid. 81 func (n CgroupMode) Valid() bool { 82 parts := strings.Split(string(n), ":") 83 switch mode := parts[0]; mode { 84 case "", hostType, privateType, nsType: 85 case containerType: 86 if len(parts) != 2 || parts[1] == "" { 87 return false 88 } 89 default: 90 return false 91 } 92 return true 93 } 94 95 // UsernsMode represents userns mode in the container. 96 type UsernsMode string 97 98 // IsHost indicates whether the container uses the host's userns. 99 func (n UsernsMode) IsHost() bool { 100 return n == hostType 101 } 102 103 // IsKeepID indicates whether container uses a mapping where the (uid, gid) on the host is kept inside of the namespace. 104 func (n UsernsMode) IsKeepID() bool { 105 parts := strings.Split(string(n), ":") 106 return parts[0] == "keep-id" 107 } 108 109 // IsNoMap indicates whether container uses a mapping where the (uid, gid) on the host is not present in the namespace. 110 func (n UsernsMode) IsNoMap() bool { 111 return n == "nomap" 112 } 113 114 // IsAuto indicates whether container uses the "auto" userns mode. 115 func (n UsernsMode) IsAuto() bool { 116 parts := strings.Split(string(n), ":") 117 return parts[0] == "auto" 118 } 119 120 // IsDefaultValue indicates whether the user namespace has the default value. 121 func (n UsernsMode) IsDefaultValue() bool { 122 return n == "" || n == defaultType 123 } 124 125 // GetAutoOptions returns an AutoUserNsOptions with the settings to automatically set up 126 // a user namespace. 127 func (n UsernsMode) GetAutoOptions() (*types.AutoUserNsOptions, error) { 128 parts := strings.SplitN(string(n), ":", 2) 129 if parts[0] != "auto" { 130 return nil, fmt.Errorf("wrong user namespace mode") 131 } 132 options := types.AutoUserNsOptions{} 133 if len(parts) == 1 { 134 return &options, nil 135 } 136 for _, o := range strings.Split(parts[1], ",") { 137 v := strings.SplitN(o, "=", 2) 138 if len(v) != 2 { 139 return nil, fmt.Errorf("invalid option specified: %q", o) 140 } 141 switch v[0] { 142 case "size": 143 s, err := strconv.ParseUint(v[1], 10, 32) 144 if err != nil { 145 return nil, err 146 } 147 options.Size = uint32(s) 148 case "uidmapping": 149 mapping, err := types.ParseIDMapping([]string{v[1]}, nil, "", "") 150 if err != nil { 151 return nil, err 152 } 153 options.AdditionalUIDMappings = append(options.AdditionalUIDMappings, mapping.UIDMap...) 154 case "gidmapping": 155 mapping, err := types.ParseIDMapping(nil, []string{v[1]}, "", "") 156 if err != nil { 157 return nil, err 158 } 159 options.AdditionalGIDMappings = append(options.AdditionalGIDMappings, mapping.GIDMap...) 160 default: 161 return nil, fmt.Errorf("unknown option specified: %q", v[0]) 162 } 163 } 164 return &options, nil 165 } 166 167 // GetKeepIDOptions returns a KeepIDUserNsOptions with the settings to keepIDmatically set up 168 // a user namespace. 169 func (n UsernsMode) GetKeepIDOptions() (*KeepIDUserNsOptions, error) { 170 parts := strings.SplitN(string(n), ":", 2) 171 if parts[0] != "keep-id" { 172 return nil, fmt.Errorf("wrong user namespace mode") 173 } 174 options := KeepIDUserNsOptions{} 175 if len(parts) == 1 { 176 return &options, nil 177 } 178 for _, o := range strings.Split(parts[1], ",") { 179 v := strings.SplitN(o, "=", 2) 180 if len(v) != 2 { 181 return nil, fmt.Errorf("invalid option specified: %q", o) 182 } 183 switch v[0] { 184 case "uid": 185 s, err := strconv.ParseUint(v[1], 10, 32) 186 if err != nil { 187 return nil, err 188 } 189 v := uint32(s) 190 options.UID = &v 191 case "gid": 192 s, err := strconv.ParseUint(v[1], 10, 32) 193 if err != nil { 194 return nil, err 195 } 196 v := uint32(s) 197 options.GID = &v 198 default: 199 return nil, fmt.Errorf("unknown option specified: %q", v[0]) 200 } 201 } 202 return &options, nil 203 } 204 205 // IsPrivate indicates whether the container uses the a private userns. 206 func (n UsernsMode) IsPrivate() bool { 207 return !(n.IsHost() || n.IsContainer()) 208 } 209 210 // Valid indicates whether the userns is valid. 211 func (n UsernsMode) Valid() bool { 212 parts := strings.Split(string(n), ":") 213 switch mode := parts[0]; mode { 214 case "", privateType, hostType, "keep-id", nsType, "auto", "nomap": 215 case containerType: 216 if len(parts) != 2 || parts[1] == "" { 217 return false 218 } 219 default: 220 return false 221 } 222 return true 223 } 224 225 // IsNS indicates a userns namespace passed in by path (ns:<path>) 226 func (n UsernsMode) IsNS() bool { 227 return strings.HasPrefix(string(n), "ns:") 228 } 229 230 // NS gets the path associated with a ns:<path> userns ns 231 func (n UsernsMode) NS() string { 232 parts := strings.SplitN(string(n), ":", 2) 233 if len(parts) > 1 { 234 return parts[1] 235 } 236 return "" 237 } 238 239 // IsContainer indicates whether container uses a container userns. 240 func (n UsernsMode) IsContainer() bool { 241 parts := strings.SplitN(string(n), ":", 2) 242 return len(parts) > 1 && parts[0] == containerType 243 } 244 245 // Container is the id of the container which network this container is connected to. 246 func (n UsernsMode) Container() string { 247 parts := strings.SplitN(string(n), ":", 2) 248 if len(parts) > 1 && parts[0] == containerType { 249 return parts[1] 250 } 251 return "" 252 } 253 254 // UTSMode represents the UTS namespace of the container. 255 type UTSMode string 256 257 // IsPrivate indicates whether the container uses its private UTS namespace. 258 func (n UTSMode) IsPrivate() bool { 259 return !(n.IsHost()) 260 } 261 262 // IsHost indicates whether the container uses the host's UTS namespace. 263 func (n UTSMode) IsHost() bool { 264 return n == hostType 265 } 266 267 // IsContainer indicates whether the container uses a container's UTS namespace. 268 func (n UTSMode) IsContainer() bool { 269 parts := strings.SplitN(string(n), ":", 2) 270 return len(parts) > 1 && parts[0] == containerType 271 } 272 273 // Container returns the name of the container whose uts namespace is going to be used. 274 func (n UTSMode) Container() string { 275 parts := strings.SplitN(string(n), ":", 2) 276 if len(parts) > 1 && parts[0] == containerType { 277 return parts[1] 278 } 279 return "" 280 } 281 282 // Valid indicates whether the UTS namespace is valid. 283 func (n UTSMode) Valid() bool { 284 parts := strings.Split(string(n), ":") 285 switch mode := parts[0]; mode { 286 case "", privateType, hostType: 287 case containerType: 288 if len(parts) != 2 || parts[1] == "" { 289 return false 290 } 291 default: 292 return false 293 } 294 return true 295 } 296 297 // IpcMode represents the container ipc stack. 298 type IpcMode string 299 300 // IsPrivate indicates whether the container uses its own private ipc namespace which cannot be shared. 301 func (n IpcMode) IsPrivate() bool { 302 return n == privateType 303 } 304 305 // IsHost indicates whether the container shares the host's ipc namespace. 306 func (n IpcMode) IsHost() bool { 307 return n == hostType 308 } 309 310 // IsShareable indicates whether the container uses its own shareable ipc namespace which can be shared. 311 func (n IpcMode) IsShareable() bool { 312 return n == shareableType 313 } 314 315 // IsContainer indicates whether the container uses another container's ipc namespace. 316 func (n IpcMode) IsContainer() bool { 317 parts := strings.SplitN(string(n), ":", 2) 318 return len(parts) > 1 && parts[0] == containerType 319 } 320 321 // IsNone indicates whether container IpcMode is set to "none". 322 func (n IpcMode) IsNone() bool { 323 return n == noneType 324 } 325 326 // IsEmpty indicates whether container IpcMode is empty 327 func (n IpcMode) IsEmpty() bool { 328 return n == "" 329 } 330 331 // Valid indicates whether the ipc mode is valid. 332 func (n IpcMode) Valid() bool { 333 return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer() 334 } 335 336 // Container returns the name of the container ipc stack is going to be used. 337 func (n IpcMode) Container() string { 338 parts := strings.SplitN(string(n), ":", 2) 339 if len(parts) > 1 && parts[0] == containerType { 340 return parts[1] 341 } 342 return "" 343 } 344 345 // PidMode represents the pid namespace of the container. 346 type PidMode string 347 348 // IsPrivate indicates whether the container uses its own new pid namespace. 349 func (n PidMode) IsPrivate() bool { 350 return !(n.IsHost() || n.IsContainer()) 351 } 352 353 // IsHost indicates whether the container uses the host's pid namespace. 354 func (n PidMode) IsHost() bool { 355 return n == hostType 356 } 357 358 // IsContainer indicates whether the container uses a container's pid namespace. 359 func (n PidMode) IsContainer() bool { 360 parts := strings.SplitN(string(n), ":", 2) 361 return len(parts) > 1 && parts[0] == containerType 362 } 363 364 // Valid indicates whether the pid namespace is valid. 365 func (n PidMode) Valid() bool { 366 parts := strings.Split(string(n), ":") 367 switch mode := parts[0]; mode { 368 case "", privateType, hostType: 369 case containerType: 370 if len(parts) != 2 || parts[1] == "" { 371 return false 372 } 373 default: 374 return false 375 } 376 return true 377 } 378 379 // Container returns the name of the container whose pid namespace is going to be used. 380 func (n PidMode) Container() string { 381 parts := strings.SplitN(string(n), ":", 2) 382 if len(parts) > 1 && parts[0] == containerType { 383 return parts[1] 384 } 385 return "" 386 } 387 388 // NetworkMode represents the container network stack. 389 type NetworkMode string 390 391 // IsNone indicates whether container isn't using a network stack. 392 func (n NetworkMode) IsNone() bool { 393 return n == noneType 394 } 395 396 // IsHost indicates whether the container uses the host's network stack. 397 func (n NetworkMode) IsHost() bool { 398 return n == hostType 399 } 400 401 // IsDefault indicates whether container uses the default network stack. 402 func (n NetworkMode) IsDefault() bool { 403 return n == defaultType 404 } 405 406 // IsPrivate indicates whether container uses its private network stack. 407 func (n NetworkMode) IsPrivate() bool { 408 return !(n.IsHost() || n.IsContainer()) 409 } 410 411 // IsContainer indicates whether container uses a container network stack. 412 func (n NetworkMode) IsContainer() bool { 413 parts := strings.SplitN(string(n), ":", 2) 414 return len(parts) > 1 && parts[0] == containerType 415 } 416 417 // Container is the id of the container which network this container is connected to. 418 func (n NetworkMode) Container() string { 419 parts := strings.SplitN(string(n), ":", 2) 420 if len(parts) > 1 && parts[0] == containerType { 421 return parts[1] 422 } 423 return "" 424 } 425 426 // UserDefined indicates user-created network 427 func (n NetworkMode) UserDefined() string { 428 if n.IsUserDefined() { 429 return string(n) 430 } 431 return "" 432 } 433 434 // IsBridge indicates whether container uses the bridge network stack 435 func (n NetworkMode) IsBridge() bool { 436 return n == bridgeType 437 } 438 439 // IsSlirp4netns indicates if we are running a rootless network stack 440 func (n NetworkMode) IsSlirp4netns() bool { 441 return n == slirpType || strings.HasPrefix(string(n), slirpType+":") 442 } 443 444 // IsPasta indicates if we are running a rootless network stack using pasta 445 func (n NetworkMode) IsPasta() bool { 446 return n == pastaType || strings.HasPrefix(string(n), pastaType+":") 447 } 448 449 // IsNS indicates a network namespace passed in by path (ns:<path>) 450 func (n NetworkMode) IsNS() bool { 451 return strings.HasPrefix(string(n), nsType) 452 } 453 454 // NS gets the path associated with a ns:<path> network ns 455 func (n NetworkMode) NS() string { 456 parts := strings.SplitN(string(n), ":", 2) 457 if len(parts) > 1 { 458 return parts[1] 459 } 460 return "" 461 } 462 463 // IsPod returns whether the network refers to pod networking 464 func (n NetworkMode) IsPod() bool { 465 return n == podType 466 } 467 468 // IsUserDefined indicates user-created network 469 func (n NetworkMode) IsUserDefined() bool { 470 return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() && !n.IsSlirp4netns() && !n.IsPasta() && !n.IsNS() 471 }