]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf tools: Fix uninitialized pathname on uncompressed fallback in filename__decompress()
authorArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 8 Jun 2026 01:43:09 +0000 (22:43 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 10 Jun 2026 21:56:01 +0000 (18:56 -0300)
filename__decompress() has an early return path for files that are not
actually compressed.  This path returns the fd from open() directly but
never writes to the pathname output parameter, leaving the caller with
an uninitialized buffer despite a successful return.

Callers like dso__decompress_kmodule_path() pass pathname to
decompress_kmodule() which uses it to set the decompressed file path.
If pathname is uninitialized, subsequent operations on the path produce
undefined behavior.

Fix by setting pathname to an empty string on the uncompressed path.
Callers already check for an empty pathname to distinguish temporary
decompressed files (which need unlink) from the original file.

Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Fixes: 7ac22b088afe26a4 ("perf tools: Add filename__decompress function")
Cc: Jiri Olsa <jolsa@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/tests/code-reading.c
tools/perf/util/disasm.c
tools/perf/util/dso.c
tools/perf/util/symbol-elf.c

index 47043a3a2fb4f833132497403eb31e385ce8a088..e82ecdc9577785e8f121f8be4c1ba158ebc43443 100644 (file)
@@ -471,8 +471,11 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
                        goto out;
                }
 
-               decomp = true;
-               objdump_name = decomp_name;
+               /* empty pathname means file wasn't actually compressed */
+               if (decomp_name[0] != '\0') {
+                       decomp = true;
+                       objdump_name = decomp_name;
+               }
        }
 
        /* Read the object code using objdump */
index 59ba88e1f7443c027aa2badbc06339723a9172cc..0a1a7e9cf3efee3eb11e97830a0a74b0dbd7eca1 100644 (file)
@@ -1577,8 +1577,11 @@ int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
                if (dso__decompress_kmodule_path(dso, symfs_filename, tmp, sizeof(tmp)) < 0)
                        return -1;
 
-               decomp = true;
-               strcpy(symfs_filename, tmp);
+               /* empty pathname means file wasn't actually compressed */
+               if (tmp[0] != '\0') {
+                       decomp = true;
+                       strcpy(symfs_filename, tmp);
+               }
        }
 
        /*
index ee06a252a54d338d41f4bd8a387e0b4c38635146..6a34717c9f31f18d60c1d7ced50a1b89d3233758 100644 (file)
@@ -343,8 +343,11 @@ int filename__decompress(const char *name, char *pathname,
         * To keep this transparent, we detect this and return the file
         * descriptor to the uncompressed file.
         */
-       if (!compressions[comp].is_compressed(name))
+       if (!compressions[comp].is_compressed(name)) {
+               if (pathname && len > 0)
+                       pathname[0] = '\0';
                return open(name, O_RDONLY | O_CLOEXEC);
+       }
 
        fd = mkostemp(tmpbuf, O_CLOEXEC);
        if (fd < 0) {
@@ -598,8 +601,11 @@ static char *dso__get_filename(struct dso *dso, const char *root_dir,
                        goto out;
                }
 
-               *decomp = true;
-               strcpy(name, newpath);
+               /* empty pathname means file wasn't actually compressed */
+               if (newpath[0] != '\0') {
+                       *decomp = true;
+                       strcpy(name, newpath);
+               }
        }
        return name;
 
index 06cfb84f86eb2f6492ffbae29b4ff9192ff3cd7e..10902a5dc6dbe6ccb26c6815caa78330ffe4ea8e 100644 (file)
@@ -920,12 +920,14 @@ int filename__read_build_id(const char *filename, struct build_id *bid)
                        return -1;
                }
                close(fd);
-               filename = path;
+               /* non-empty path means a temp file was created */
+               if (path[0] != '\0')
+                       filename = path;
        }
 
        err = read_build_id(filename, bid);
 
-       if (m.comp)
+       if (m.comp && filename == path)
                unlink(filename);
        return err;
 }