(opts *handlerOpts)
| 477 | } |
| 478 | |
| 479 | func applyNetworkSettings(opts *handlerOpts) (err error) { |
| 480 | portMapOpts, err := getPortMapOpts(opts) |
| 481 | if err != nil { |
| 482 | return err |
| 483 | } |
| 484 | if !rootlessutil.IsRootlessChild() && len(opts.ports) > 0 { |
| 485 | // When running in rootful mode, reserve the ports on the host |
| 486 | // so that the ports appears on /proc/net/tcp. |
| 487 | // |
| 488 | // This also prevents other processes from binding to the same ports. |
| 489 | // |
| 490 | // Note that in rootless mode this is not necessary because |
| 491 | // RootlessKit's port driver already reserves the ports. |
| 492 | // |
| 493 | // See https://github.com/lima-vm/lima/issues/4085 |
| 494 | // |
| 495 | // Similar patterns are used in Docker and Podman. |
| 496 | // - https://github.com/moby/moby/pull/48132 |
| 497 | // - https://github.com/containers/podman/pull/23446 |
| 498 | reserverCmd := exec.Command("sleep", "infinity") |
| 499 | for _, p := range opts.ports { |
| 500 | protocol := p.Protocol |
| 501 | if !strings.HasSuffix(protocol, "4") && !strings.HasSuffix(protocol, "6") { |
| 502 | // e.g. "tcp" -> "tcp4" |
| 503 | protocol += "4" |
| 504 | } |
| 505 | hostAddr := net.JoinHostPort(p.HostIP, strconv.Itoa(int(p.HostPort))) |
| 506 | f, err := reserveSocket(protocol, hostAddr) |
| 507 | if err != nil { |
| 508 | log.L.WithError(err).Warnf("cannot reserve the port %s/%s", hostAddr, protocol) |
| 509 | continue |
| 510 | } |
| 511 | reserverCmd.ExtraFiles = append(reserverCmd.ExtraFiles, f) |
| 512 | } |
| 513 | if err := reserverCmd.Start(); err != nil { |
| 514 | return fmt.Errorf("cannot start the port reserver process: %w", err) |
| 515 | } |
| 516 | reserverCmdPid := reserverCmd.Process.Pid |
| 517 | log.L.Debugf("started the port reserver process (pid=%d)", reserverCmdPid) |
| 518 | defer func() { |
| 519 | if err != nil { |
| 520 | log.L.Debugf("killing the port reserver process (pid=%d)", reserverCmdPid) |
| 521 | _ = reserverCmd.Process.Kill() |
| 522 | _ = os.RemoveAll(filepath.Dir(portReserverPidFilePath(opts.state.Annotations[labels.Namespace], opts.state.ID))) |
| 523 | } |
| 524 | }() |
| 525 | if err := writePidFile(portReserverPidFilePath(opts.state.Annotations[labels.Namespace], opts.state.ID), reserverCmdPid); err != nil { |
| 526 | return fmt.Errorf("cannot write the pid file of the port reserver process: %w", err) |
| 527 | } |
| 528 | } |
| 529 | nsPath, err := getNetNSPath(opts.state) |
| 530 | if err != nil { |
| 531 | return err |
| 532 | } |
| 533 | ctx := context.Background() |
| 534 | hs, err := hostsstore.New(opts.dataStore, opts.state.Annotations[labels.Namespace]) |
| 535 | if err != nil { |
| 536 | return err |
no test coverage detected
searching dependent graphs…