diff options
Diffstat (limited to 'internal/namespace/namespace.go')
| -rw-r--r-- | internal/namespace/namespace.go | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/internal/namespace/namespace.go b/internal/namespace/namespace.go index e2ef2f1..ab3797d 100644 --- a/internal/namespace/namespace.go +++ b/internal/namespace/namespace.go @@ -69,11 +69,20 @@ func VerifyArguments(args []string) error { // Bootstrap ensures the process is running in an isolated user and network namespace. // It writes the embedded C launcher to a temporary file and replaces the current process. -func Bootstrap() error { +func Bootstrap() (err error) { if IsIsolated() { return nil } + var fdsToClose []int + defer func() { + if err != nil { + for _, fd := range fdsToClose { + _ = syscall.Close(fd) + } + } + }() + // 0. Validate current arguments for null bytes before proceeding. // If any argument contains a null byte, syscall.Exec will fail with 'invalid argument'. for i, arg := range os.Args { @@ -118,6 +127,7 @@ func Bootstrap() error { _ = os.Remove(launcherPath) return fmt.Errorf("failed to open launcher for exec: %w", err) } + fdsToClose = append(fdsToClose, execFd) // Close the write file descriptor (to avoid ETXTBSY) _ = tmpFile.Close() @@ -152,6 +162,8 @@ func Bootstrap() error { if err != nil { return fmt.Errorf("failed to open host netns: %w", err) } + fdsToClose = append(fdsToClose, hostNetFd) + // Clear close-on-exec so it remains open across syscall.Exec if flags, err := unix.FcntlInt(uintptr(hostNetFd), unix.F_GETFD, 0); err == nil { _, _ = unix.FcntlInt(uintptr(hostNetFd), unix.F_SETFD, flags&^unix.FD_CLOEXEC) @@ -160,15 +172,17 @@ func Bootstrap() error { env := append(os.Environ(), fmt.Sprintf("WG_WRAP_HOST_NETNS_FD=%d", hostNetFd)) // Open a host UDP socket on 0.0.0.0:0 before unsharing network namespace. - laddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:0") - if err == nil { - if conn, err := net.ListenUDP("udp", laddr); err == nil { - if file, err := conn.File(); err == nil { + laddr, errAddr := net.ResolveUDPAddr("udp", "0.0.0.0:0") + if errAddr == nil { + if conn, errConn := net.ListenUDP("udp", laddr); errConn == nil { + if file, errFile := conn.File(); errFile == nil { hostSocketFd := file.Fd() - if flags, err := unix.FcntlInt(hostSocketFd, unix.F_GETFD, 0); err == nil { + if flags, fcntlErr := unix.FcntlInt(hostSocketFd, unix.F_GETFD, 0); fcntlErr == nil { _, _ = unix.FcntlInt(hostSocketFd, unix.F_SETFD, flags&^unix.FD_CLOEXEC) } env = append(env, fmt.Sprintf("WG_WRAP_HOST_SOCKET_FD=%d", hostSocketFd)) + fdsToClose = append(fdsToClose, int(hostSocketFd)) + _ = conn.Close() } } } |
