From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Alan Maguire <alan.maguire@oracle.com>
Cc: Jiri Olsa <jolsa@kernel.org>,
Clark Williams <williams@redhat.com>,
dwarves@vger.kernel.org, bpf@vger.kernel.org,
Andrii Nakryiko <andrii@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH 14/31] btf_encoder, libctf: Add elf_strptr NULL checks and fix kfunc bounds
Date: Wed, 29 Jul 2026 16:07:14 -0300 [thread overview]
Message-ID: <20260729190733.72876-15-acme@kernel.org> (raw)
In-Reply-To: <20260729190733.72876-1-acme@kernel.org>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
Several elf_strptr() calls in btf_encoder and libctf lacked NULL checks,
which would cause segfaults on malformed ELF files:
1. btf_encoder__new(): strcmp(secname, PERCPU_SECTION) crashes if
elf_section_by_idx() returns a valid section but elf_strptr() fails
internally.
2. btf_encoder__collect_kfuncs(): two elf_strptr() calls for symbol
names passed to strstarts()/get_func_name() without NULL guards.
3. libctf.c ctf__encode(): strcmp(secname, ".SUNW_ctf") without
NULL check.
Also fix is_sym_kfunc_set() bounds check: the original `off >= d_size`
only verified the start offset, but accessing set->flags could read
past the buffer. Changed to `off + sizeof(*set) > d_size` and added
an `off < 0` guard to prevent signed-to-unsigned wraparound when the
symbol address is below the section base.
Before: malformed ELF with invalid string table causes SIGSEGV
After: gracefully skips bad entries
Fixes: 72e88f29c6f7e142 ("pahole: Inject kfunc decl tags into BTF")
Fixes: ff34e733a0c23bf4 ("btf_encoder: Allow encoding VARs from many sections")
Fixes: dcef613288086156 ("libctf: give up "for now" on using libelf to add a section to an existing file")
Reported-by: Sashiko:gemini-3-1-pro-preview
Assisted-by: Claude:claude-sonnet-4-5
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
btf_encoder.c | 10 ++++++----
libctf.c | 2 +-
pahole.c | 14 +++++++++++---
3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/btf_encoder.c b/btf_encoder.c
index 5c12e79f5ef648ba..c7b71b5b741bfa6f 100644
--- a/btf_encoder.c
+++ b/btf_encoder.c
@@ -2099,14 +2099,14 @@ static int is_sym_kfunc_set(GElf_Sym *sym, const char *name, Elf_Data *idlist, s
{
void *ptr = idlist->d_buf;
struct btf_id_set8 *set;
- size_t off;
+ ptrdiff_t off;
/* kfuncs are only found in BTF_SET8's */
if (!strstarts(name, BTF_ID_SET8_PFX))
return false;
off = sym->st_value - idlist_addr;
- if (off >= idlist->d_size) {
+ if (off < 0 || (size_t)off + sizeof(*set) > idlist->d_size) {
fprintf(stderr, "%s: symbol '%s' out of bounds\n", __func__, name);
return false;
}
@@ -2276,7 +2276,7 @@ static int btf_encoder__collect_kfuncs(struct btf_encoder *encoder)
continue;
name = elf_strptr(elf, strtabidx, sym.st_name);
- if (!is_sym_kfunc_set(&sym, name, idlist, idlist_addr))
+ if (name == NULL || !is_sym_kfunc_set(&sym, name, idlist, idlist_addr))
continue;
range.start = sym.st_value;
@@ -2305,6 +2305,8 @@ static int btf_encoder__collect_kfuncs(struct btf_encoder *encoder)
continue;
name = elf_strptr(elf, strtabidx, sym.st_name);
+ if (name == NULL)
+ continue;
func = get_func_name(name);
if (!func)
continue;
@@ -2879,7 +2881,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam
if (encoder->encode_vars & BTF_VAR_GLOBAL)
encoder->secinfo[shndx].include = true;
- if (strcmp(secname, PERCPU_SECTION) == 0) {
+ if (secname != NULL && strcmp(secname, PERCPU_SECTION) == 0) {
found_percpu = true;
if (encoder->encode_vars & BTF_VAR_PERCPU)
encoder->secinfo[shndx].include = true;
diff --git a/libctf.c b/libctf.c
index 8e31e3d550ebd51a..72f9949a2d25b3d9 100644
--- a/libctf.c
+++ b/libctf.c
@@ -674,7 +674,7 @@ int ctf__encode(struct ctf *ctf, uint8_t flags)
if (shdr == NULL)
continue;
char *secname = elf_strptr(elf, strndx, shdr->sh_name);
- if (strcmp(secname, ".SUNW_ctf") == 0) {
+ if (secname != NULL && strcmp(secname, ".SUNW_ctf") == 0) {
data = elf_getdata(scn, data);
goto out_update;
}
diff --git a/pahole.c b/pahole.c
index 6ba3f578c28570a1..0e2acc35d6d679f0 100644
--- a/pahole.c
+++ b/pahole.c
@@ -2361,6 +2361,11 @@ static int pipe_seek(FILE *fp, off_t offset)
chunk = offset;
}
+ /* On EOF (not I/O error), clear errno so callers don't
+ * pick up a stale value from an earlier successful fread. */
+ if (!ferror(fp))
+ errno = 0;
+
return offset == 0 ? 0 : -1;
}
@@ -2583,8 +2588,9 @@ static int prototype__stdio_fprintf_value(struct prototype *prototype, struct ty
if (instance == NULL)
return -ENOMEM;
+ errno = 0;
if (type__instance_read_once(header, input) < 0) {
- printed = -errno;
+ printed = errno ? -errno : -EIO;
fprintf(stderr, "pahole: --header (%s) type couldn't be read\n", conf.header_type);
goto out;
}
@@ -2666,8 +2672,9 @@ static int prototype__stdio_fprintf_value(struct prototype *prototype, struct ty
free(member_name);
+ errno = 0;
if (pipe_seek(input, seek_bytes) < 0) {
- printed = -errno;
+ printed = errno ? -errno : -EIO;
fprintf(stderr, "Couldn't --seek_bytes %s (%" PRIu64 "\n", conf.seek_bytes, seek_bytes);
goto out;
}
@@ -2717,8 +2724,9 @@ static int prototype__stdio_fprintf_value(struct prototype *prototype, struct ty
seek_bytes -= ftell(input);
}
+ errno = 0;
if (pipe_seek(input, seek_bytes) < 0) {
- printed = -errno;
+ printed = errno ? -errno : -EIO;
fprintf(stderr, "Couldn't --seek_bytes %s (%" PRIu64 "\n", conf.seek_bytes, seek_bytes);
goto out;
}
--
2.55.0
next prev parent reply other threads:[~2026-07-29 19:08 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-29 19:07 [PATCHES 00/31] pahole: Bug fixes and small improvements Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 01/31] cmake: Update minimum required version from 3.5 to 3.10 Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 02/31] Fix -Wsign-compare warnings across the codebase Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 03/31] btf_encoder: Fix interior pointer free and missing NULL check Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 04/31] dwarves: Fix missing list head initialization in type__clone_members Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 05/31] pahole: Fix instance memory leak on early returns in prototype__stdio_fprintf_value Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 06/31] ctf_loader, libctf: Fix error path resource leaks Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 07/31] dwarves: Don't search for holes before member byte sizes are cached Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 08/31] dwarf_loader: Allocate type_dcu via dwarf_cu__new to fix dangling stack pointer Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 09/31] dwarf_loader: Fix annotation failure leaks in variable and typedef creation Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 10/31] btf_encoder: Use btf_encoder__tag_type() for all type ID computations Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 11/31] pahole: Fix --errno typo that decrements instead of negating Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 12/31] dwarves: Fix heap buffer overflow in languages__parse realloc Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 13/31] btf_encoder: Fix early cleanup crashes in btf_encoder__new/delete Arnaldo Carvalho de Melo
2026-07-29 19:07 ` Arnaldo Carvalho de Melo [this message]
2026-07-29 19:07 ` [PATCH 15/31] dwarf_loader: Fix --fixup_silly_bitfields condition check Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 16/31] dwarf_loader: Skip libdw__lock when elfutils is built thread-safe Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 17/31] dwarf_loader: Fix data race in tag__init() decl_file string cache Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 18/31] pahole: Fix parse_btf_features("all") being a silent no-op Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 19/31] dwarves: Fix variable shadowing in __cus__find_struct_by_name() Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 20/31] dutil: Add exec_objcopy() shell-injection-safe helper Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 21/31] btf_encoder: Fall back to objcopy when llvm-objcopy is not available Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 22/31] dwarf_loader, btf_loader: Replace stale FIXME/XXX comments with explanations Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 23/31] pahole: Skip inline expansions during BTF encoding Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 24/31] pahole: Use fseek for seekable files in --prettify and --seek_bytes Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 25/31] pahole: Guard pipe_seek() against negative offsets Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 26/31] gobuffer: Remove 5 dead functions found via coverage analysis Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 27/31] dwarves: Remove 6 " Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 28/31] pfunct, dwarves_fprintf: Mark file-local functions as static Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 29/31] btf_encoder: Fix multi-dimensional array encoding Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 30/31] btf_loader: Fix multi-dimensional array loading Arnaldo Carvalho de Melo
2026-07-29 19:07 ` [PATCH 31/31] btfdiff: Remove --flat_arrays now that pahole encodes multi dim arrays in BTF Arnaldo Carvalho de Melo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260729190733.72876-15-acme@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=alan.maguire@oracle.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=jolsa@kernel.org \
--cc=williams@redhat.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox