From fd3937cf62003ef3df75d0f816cae5475b1f0a72 Mon Sep 17 00:00:00 2001 From: Tushar Verma Date: Fri, 14 Aug 2026 12:02:45 +0530 Subject: [PATCH] build: do not leak context tmpdir ParseBuildOpts downloads a URL or stdin context into a temp dir and stores it in TmpDirToClose, but the caller only removes that when ParseBuildOpts returns successfully. Every error return after the download leaks it, including the authfile check reproduced in #22642 and a plain build of a git URL with no Containerfile, which leaves the whole clone behind. Use the same succeeded guard TempDirForURL itself uses, one level up so it covers both tmpdir call sites and the logfile next to them. Fixes: #22642 Signed-off-by: Tushar Verma --- cmd/podman/common/build.go | 17 +++++++++++++++++ test/system/070-build.bats | 12 ++++++++++++ 2 files changed, 29 insertions(+) diff --git a/cmd/podman/common/build.go b/cmd/podman/common/build.go index c54b048dfe..2e9f98830d 100644 --- a/cmd/podman/common/build.go +++ b/cmd/podman/common/build.go @@ -195,6 +195,22 @@ func ParseBuildOpts(cmd *cobra.Command, args []string, buildOpts *BuildFlagsWrap contextDir string apiBuildOpts entities.BuildOptions ) + // The caller only cleans up TmpDirToClose and LogFileToClose when we + // return successfully, so clean them up ourselves on every error path. + succeeded := false + defer func() { + if succeeded { + return + } + if apiBuildOpts.TmpDirToClose != "" { + if err := os.RemoveAll(apiBuildOpts.TmpDirToClose); err != nil { + logrus.Errorf("Removing temporary directory %q: %v", apiBuildOpts.TmpDirToClose, err) + } + } + if apiBuildOpts.LogFileToClose != nil { + apiBuildOpts.LogFileToClose.Close() + } + }() if len(args) > 0 { // The context directory could be a URL. Try to handle that. tempDir, subDir, err := buildahDefine.TempDirForURL("", "buildah", args[0]) @@ -283,6 +299,7 @@ func ParseBuildOpts(cmd *cobra.Command, args []string, buildOpts *BuildFlagsWrap apiBuildOpts.ContainerFiles = containerFiles apiBuildOpts.Authfile = buildOpts.Authfile + succeeded = true return &apiBuildOpts, err } diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 38ae11b032..a7c891afbc 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -34,6 +34,18 @@ EOF run_podman rmi -f $imgname } +# 22642: a failed flag check used to leak the downloaded context directory +@test "podman build - no tmpdir leak on early failure" { + tmpdir=$PODMAN_TMPDIR/build-tmp + mkdir -p $tmpdir + + TMPDIR=$tmpdir run_podman 125 build --authfile=$PODMAN_TMPDIR/bogus-authfile - <<<"from scratch" + is "$output" ".*credential file is not accessible.*" "expected authfile error" + + run ls -A $tmpdir + assert "$output" == "" "leftover files in TMPDIR after failed build" +} + @test "podman buildx - basic test" { rand_filename=$(random_string 20) rand_content=$(random_string 50)