From ffc6092b8d1fe309b8c562f3c38e6d2087e4fae1 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 12 Nov 2025 13:13:48 -0800 Subject: [PATCH 1/4] [1.4] libct: startInitialization: add defer close This function calls Init what normally never returns, so the defer only works if there is an error and we can safely use it to close those fds we opened. This was done for most but not all fds. Reported in issue 5008. Reported-by: Arina Cherednik Signed-off-by: Kir Kolyshkin (cherry picked from commit 88f897160cbe25e6416e8167ed4bda9a21613634) Signed-off-by: Aleksa Sarai --- libcontainer/init_linux.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 0171b4d9f..632d7c349 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -175,6 +175,7 @@ func startInitialization() (retErr error) { return fmt.Errorf("unable to convert _LIBCONTAINER_LOGPIPE: %w", err) } logPipe := os.NewFile(uintptr(logFd), "logpipe") + defer logPipe.Close() logrus.SetOutput(logPipe) logrus.SetFormatter(new(logrus.JSONFormatter)) @@ -190,6 +191,7 @@ func startInitialization() (retErr error) { return fmt.Errorf("unable to convert _LIBCONTAINER_FIFOFD: %w", err) } fifoFile = os.NewFile(uintptr(fifoFd), "initfifo") + defer fifoFile.Close() } var consoleSocket *os.File From 0af85cbca84afbd603c703e8366c78ba98c6079d Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 12 Nov 2025 13:28:57 -0800 Subject: [PATCH 2/4] [1.4] libct: newProcessComm: close fds on error Reported in issue 5008. Reported-by: Arina Cherednik Signed-off-by: Kir Kolyshkin (cherry picked from commit c24965b742468a5307fd268ef484b173a3e52f2b) Signed-off-by: Aleksa Sarai --- libcontainer/process_linux.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go index fddb03408..d9c441ec5 100644 --- a/libcontainer/process_linux.go +++ b/libcontainer/process_linux.go @@ -70,7 +70,7 @@ type processComm struct { logPipeChild *os.File } -func newProcessComm() (*processComm, error) { +func newProcessComm() (_ *processComm, retErr error) { var ( comm processComm err error @@ -79,10 +79,24 @@ func newProcessComm() (*processComm, error) { if err != nil { return nil, fmt.Errorf("unable to create init pipe: %w", err) } + defer func() { + if retErr != nil { + comm.initSockParent.Close() + comm.initSockChild.Close() + } + }() + comm.syncSockParent, comm.syncSockChild, err = newSyncSockpair("sync") if err != nil { return nil, fmt.Errorf("unable to create sync pipe: %w", err) } + defer func() { + if retErr != nil { + comm.syncSockParent.Close() + comm.syncSockChild.Close() + } + }() + comm.logPipeParent, comm.logPipeChild, err = os.Pipe() if err != nil { return nil, fmt.Errorf("unable to create log pipe: %w", err) From d934c6dd9e95931a8fe22196ab855e41c73500d7 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 12 Nov 2025 13:35:24 -0800 Subject: [PATCH 3/4] [1.4] libct: mountFd: close mountFile on error Reported in issue 5008. Reported-by: Arina Cherednik Signed-off-by: Kir Kolyshkin (cherry picked from commit 8a9b4dcda6de12549bdc7d0824ed9eea0fcea693) Signed-off-by: Aleksa Sarai --- libcontainer/mount_linux.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libcontainer/mount_linux.go b/libcontainer/mount_linux.go index 9d4b5dcef..06df6cbbf 100644 --- a/libcontainer/mount_linux.go +++ b/libcontainer/mount_linux.go @@ -250,7 +250,7 @@ func syscallMode(i fs.FileMode) (o uint32) { // process will need to do an old-fashioned mount(2) themselves. // // This helper is only intended to be used by goCreateMountSources. -func mountFd(nsHandles *userns.Handles, m *configs.Mount) (*mountSource, error) { +func mountFd(nsHandles *userns.Handles, m *configs.Mount) (_ *mountSource, retErr error) { if !m.IsBind() { return nil, errors.New("new mount api: only bind-mounts are supported") } @@ -261,6 +261,11 @@ func mountFd(nsHandles *userns.Handles, m *configs.Mount) (*mountSource, error) var mountFile *os.File var sourceType mountSourceType + defer func() { + if retErr != nil && mountFile != nil { + mountFile.Close() + } + }() // Ideally, we would use OPEN_TREE_CLONE for everything, because we can // be sure that the file descriptor cannot be used to escape outside of From 5dac7379e73cfcedeeb03e5f6577f87196500975 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 12 Nov 2025 13:39:33 -0800 Subject: [PATCH 4/4] [1.4] notify_socket: close fds on error Reported in issue 5008. Reported-by: Arina Cherednik Signed-off-by: Kir Kolyshkin (cherry picked from commit 93792e6c1362954ffb2be86789d05c342fbfdda7) Signed-off-by: Aleksa Sarai --- notify_socket.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/notify_socket.go b/notify_socket.go index c3eddaf85..5dd5d5007 100644 --- a/notify_socket.go +++ b/notify_socket.go @@ -175,12 +175,18 @@ func notifyHost(client *net.UnixConn, ready []byte, pid1 int) error { var errUnexpectedRead = errors.New("unexpected read from synchronization pipe") // sdNotifyBarrier performs synchronization with systemd by means of the sd_notify_barrier protocol. -func sdNotifyBarrier(client *net.UnixConn) error { +func sdNotifyBarrier(client *net.UnixConn) (retErr error) { // Create a pipe for communicating with systemd daemon. pipeR, pipeW, err := os.Pipe() if err != nil { return err } + defer func() { + if retErr != nil { + pipeW.Close() + pipeR.Close() + } + }() // Get the FD for the unix socket file to be able to use sendmsg. clientFd, err := client.File()