summaryrefslogtreecommitdiff
path: root/internal/namespace/namespace.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/namespace/namespace.go')
-rw-r--r--internal/namespace/namespace.go26
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()
}
}
}