Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions app/child.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,66 @@
package app

import (
"context"
"fmt"
"log"
"log/slog"
"os"
"os/exec"
"syscall"
"time"

"github.com/cenkalti/backoff/v5"
"github.com/coder/boundary/jail"
"golang.org/x/sys/unix"
)

// waitForInterface waits for a network interface to appear in the namespace.
// It retries checking for the interface with exponential backoff up to the specified timeout.
func waitForInterface(interfaceName string, timeout time.Duration) error {
b := backoff.NewExponentialBackOff()
b.InitialInterval = 50 * time.Millisecond
b.MaxInterval = 500 * time.Millisecond
b.Multiplier = 2.0

ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()

operation := func() (bool, error) {
cmd := exec.Command("ip", "link", "show", interfaceName)
cmd.SysProcAttr = &syscall.SysProcAttr{
AmbientCaps: []uintptr{uintptr(unix.CAP_NET_ADMIN)},
}

err := cmd.Run()
if err != nil {
return false, fmt.Errorf("interface %s not found: %w", interfaceName, err)
}
// Interface exists
return true, nil
}

_, err := backoff.Retry(ctx, operation, backoff.WithBackOff(b))
if err != nil {
return fmt.Errorf("interface %s did not appear within %v: %w", interfaceName, timeout, err)
}

return nil
}

func RunChild(logger *slog.Logger, args []string) error {
logger.Info("boundary CHILD process is started")

vethNetJail := os.Getenv("VETH_JAIL_NAME")
if vethNetJail == "" {
return fmt.Errorf("VETH_JAIL_NAME environment variable is not set")
}

// Wait for the veth interface to be moved into the namespace by the parent process
if err := waitForInterface(vethNetJail, 5*time.Second); err != nil {
return fmt.Errorf("failed to wait for interface %s: %w", vethNetJail, err)
}

err := jail.SetupChildNetworking(vethNetJail)
if err != nil {
return fmt.Errorf("failed to setup child networking: %v", err)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/coder/boundary
go 1.24.0

require (
github.com/cenkalti/backoff/v5 v5.0.3
github.com/coder/serpent v0.10.0
github.com/stretchr/testify v1.8.4
golang.org/x/sys v0.38.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tE
cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/charmbracelet/lipgloss v0.8.0 h1:IS00fk4XAHcf8uZKc3eHeMUTCxUH6NkaTrdyCQk84RU=
github.com/charmbracelet/lipgloss v0.8.0/go.mod h1:p4eYUZZJ/0oXTuCQKFF8mqyKCz0ja6y+7DniDDw5KKU=
github.com/coder/pretty v0.0.0-20230908205945-e89ba86370e0 h1:3A0ES21Ke+FxEM8CXx9n47SZOKOpgSE1bbJzlE4qPVs=
Expand Down