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
3 changes: 2 additions & 1 deletion internal/adapters/dns/powerdns.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ func (b *PowerDNSBackend) CreateZone(ctx context.Context, zoneName string, names
}

// Add an initial SOA record to satisfy PowerDNS requirements for Native zones
soaContent := fmt.Sprintf("%s hostmaster.%s 1 10800 3600 604800 3600", nameservers[0], zoneName)
ns := nameservers[0] // validated above
soaContent := fmt.Sprintf("%s hostmaster.%s 1 10800 3600 604800 3600", ns, zoneName)
soaRecord := ports.RecordSet{
Name: zoneName,
Type: "SOA",
Expand Down
15 changes: 13 additions & 2 deletions internal/core/services/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"log/slog"
"math"
"net"
"strconv"
"strings"
Expand Down Expand Up @@ -1005,6 +1006,10 @@ func (s *InstanceService) completeResize(ctx context.Context, tenantID uuid.UUID

// 2. Compute resize (now that quota is settled)
newCpuNano := int64(newIT.VCPUs) * NanoCPUsPerVCPU
const maxMemoryMB = math.MaxInt64 / BytesPerMB
if int64(newIT.MemoryMB) > maxMemoryMB {
return fmt.Errorf("memory size overflows int64: %d MB", newIT.MemoryMB)
}
newMemoryBytes := int64(newIT.MemoryMB) * BytesPerMB
if err := s.compute.ResizeInstance(ctx, target, newCpuNano, newMemoryBytes); err != nil {
platform.InstanceOperationsTotal.WithLabelValues("resize", "failure").Inc()
Expand Down Expand Up @@ -1495,7 +1500,13 @@ func (s *InstanceService) findAvailableIP(ipNet *net.IPNet, usedIPs map[string]b
ip := make(net.IP, len(ipNet.IP))
copy(ip, ipNet.IP)

for {
ones, _ := ipNet.Mask.Size()
maxIPs := uint64(1) << (32 - ones)
if maxIPs > 1<<16 {
maxIPs = 1 << 16 // cap at 65536 to prevent unbounded iteration
}

for iterations := uint64(0); iterations < maxIPs; iterations++ {
// Increment IP
for i := len(ip) - 1; i >= 0; i-- {
ip[i]++
Expand All @@ -1517,7 +1528,7 @@ func (s *InstanceService) findAvailableIP(ipNet *net.IPNet, usedIPs map[string]b
return displayIP, nil
}
}
return "", fmt.Errorf("no available IPs in subnet")
return "", fmt.Errorf("no available IPs in subnet after %d attempts", maxIPs)
}

func (s *InstanceService) Exec(ctx context.Context, idOrName string, cmd []string) (string, error) {
Expand Down
6 changes: 6 additions & 0 deletions internal/repositories/docker/snapshot_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package docker

import (
"fmt"
"os"
"path/filepath"
"strings"
)
Expand Down Expand Up @@ -53,6 +54,11 @@ func validateSnapshotPath(p string) (string, error) {
return "", fmt.Errorf("snapshot path is not canonical: %q (cleaned %q)", p, cleaned)
}

// Reject symlinks to prevent traversal through symlink-based escapes.
if info, err := os.Lstat(cleaned); err == nil && (info.Mode()&os.ModeSymlink) != 0 {
return "", fmt.Errorf("snapshot path is a symlink: %q", p)
}

// After Clean a leading `..` cannot survive on an absolute path, but reject
// any embedded `..` segment defensively for older filepath behavior on
// other platforms.
Expand Down
7 changes: 7 additions & 0 deletions internal/repositories/ovs/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"
"log/slog"
"net"
"os/exec"
"regexp"
"strings"
Expand Down Expand Up @@ -145,6 +146,9 @@ func (a *OvsAdapter) CreateVXLANTunnel(ctx context.Context, bridge string, vni i
if !bridgeNameRegex.MatchString(bridge) {
return errors.New(errors.InvalidInput, invalidBridgeNameMsg)
}
if net.ParseIP(remoteIP) == nil {
return errors.New(errors.InvalidInput, "invalid remote IP address")
}

tunnelName := fmt.Sprintf("vxlan-%s", strings.ReplaceAll(remoteIP, ".", "-"))
cmd := a.exec.CommandContext(ctx, a.ovsPath,
Expand All @@ -163,6 +167,9 @@ func (a *OvsAdapter) CreateVXLANTunnel(ctx context.Context, bridge string, vni i
}

func (a *OvsAdapter) DeleteVXLANTunnel(ctx context.Context, bridge string, remoteIP string) error {
if net.ParseIP(remoteIP) == nil {
return errors.New(errors.InvalidInput, "invalid remote IP address")
}
tunnelName := fmt.Sprintf("vxlan-%s", strings.ReplaceAll(remoteIP, ".", "-"))
return a.DeletePort(ctx, bridge, tunnelName)
}
Expand Down
Loading