From a55277da471a7b559e7fa45bb07024b7629e7ba2 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sun, 12 Jan 2025 14:45:16 -0700 Subject: [PATCH] ufs: ensure `fsDirfd` always gets closed (fix file descriptor leak) Signed-off-by: Matthew Penner --- internal/ufs/fs_unix.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/internal/ufs/fs_unix.go b/internal/ufs/fs_unix.go index a6842b2c..87b83c77 100644 --- a/internal/ufs/fs_unix.go +++ b/internal/ufs/fs_unix.go @@ -621,7 +621,7 @@ func (fs *UnixFS) openat(dirfd int, name string, flag int, mode FileMode) (int, if err == unix.EINTR { continue } - return 0, convertErrorType(err) + return -1, convertErrorType(err) } // If we are using openat2, we don't need the additional security checks. @@ -681,11 +681,11 @@ func (fs *UnixFS) _openat(dirfd int, name string, flag int, mode uint32) (int, e case err == nil: return fd, nil case err == unix.EINTR: - return 0, err + return -1, err case err == unix.EAGAIN: - return 0, err + return -1, err default: - return 0, &PathError{Op: "openat", Path: name, Err: err} + return -1, &PathError{Op: "openat", Path: name, Err: err} } } @@ -720,11 +720,11 @@ func (fs *UnixFS) _openat2(dirfd int, name string, flag, mode uint64) (int, erro case err == nil: return fd, nil case err == unix.EINTR: - return 0, err + return -1, err case err == unix.EAGAIN: - return 0, err + return -1, err default: - return 0, &PathError{Op: "openat2", Path: name, Err: err} + return -1, &PathError{Op: "openat2", Path: name, Err: err} } } @@ -768,7 +768,11 @@ func (fs *UnixFS) safePath(path string) (dirfd int, file string, closeFd func(), // trim slashes. dir = strings.TrimSuffix(dir, "/") dirfd, err = fs.openat(fsDirfd, dir, O_DIRECTORY|O_RDONLY, 0) - if dirfd != 0 { + if err != nil { + // An error occurred while opening the directory, but we already opened + // the filesystem root, so we still need to ensure it gets closed. + closeFd = func() { _ = unix.Close(fsDirfd) } + } else { // Set closeFd to close the newly opened directory file descriptor. closeFd = func() { _ = unix.Close(dirfd) @@ -776,6 +780,7 @@ func (fs *UnixFS) safePath(path string) (dirfd int, file string, closeFd func(), } } + // Return dirfd, name, the closeFd func, and err return }