(process *Process)
| 307 | } |
| 308 | |
| 309 | func (c *Container) start(process *Process) (retErr error) { |
| 310 | if c.config.Cgroups.Resources.SkipDevices { |
| 311 | return errors.New("can't start container with SkipDevices set") |
| 312 | } |
| 313 | |
| 314 | if c.config.RootlessEUID && len(process.AdditionalGroups) > 0 { |
| 315 | // We cannot set any additional groups in a rootless container |
| 316 | // and thus we bail if the user asked us to do so. |
| 317 | return errors.New("cannot set any additional groups in a rootless container") |
| 318 | } |
| 319 | |
| 320 | if process.Init { |
| 321 | if c.initProcessStartTime != 0 { |
| 322 | return errors.New("container already has init process") |
| 323 | } |
| 324 | if err := c.createExecFifo(); err != nil { |
| 325 | return err |
| 326 | } |
| 327 | defer func() { |
| 328 | if retErr != nil { |
| 329 | c.deleteExecFifo() |
| 330 | } |
| 331 | }() |
| 332 | } |
| 333 | |
| 334 | parent, err := c.newParentProcess(process) |
| 335 | if err != nil { |
| 336 | return fmt.Errorf("unable to create new parent process: %w", err) |
| 337 | } |
| 338 | // We do not need the cloned binaries once the process is spawned. |
| 339 | defer process.closeClonedExes() |
| 340 | |
| 341 | // Before starting "runc init", mark all non-stdio open files as O_CLOEXEC |
| 342 | // to make sure we don't leak any files into "runc init". Any files to be |
| 343 | // passed to "runc init" through ExtraFiles will get dup2'd by the Go |
| 344 | // runtime and thus their O_CLOEXEC flag will be cleared. This is some |
| 345 | // additional protection against attacks like CVE-2024-21626, by making |
| 346 | // sure we never leak files to "runc init" we didn't intend to. |
| 347 | if err := utils.CloseExecFrom(3); err != nil { |
| 348 | return fmt.Errorf("unable to mark non-stdio fds as cloexec: %w", err) |
| 349 | } |
| 350 | |
| 351 | if logsDone := parent.forwardChildLogs(); logsDone != nil { |
| 352 | defer func() { |
| 353 | // Wait for log forwarder to finish. This depends on |
| 354 | // runc init closing the _LIBCONTAINER_LOGPIPE log fd. |
| 355 | err := <-logsDone |
| 356 | if err != nil { |
| 357 | // runc init errors are important; make sure retErr has them. |
| 358 | err = fmt.Errorf("runc init error(s): %w", err) |
| 359 | if retErr != nil { |
| 360 | retErr = fmt.Errorf("%w; %w", retErr, err) |
| 361 | } else { |
| 362 | retErr = err |
| 363 | } |
| 364 | } |
| 365 | }() |
| 366 | } |
no test coverage detected