git: fa848d4d0c03 - main - rtld: more caution when parsing in digest_notes()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 14 Sep 2026 21:55:45 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=fa848d4d0c0371cdbf39265b6528f4c61bc02c7d
commit fa848d4d0c0371cdbf39265b6528f4c61bc02c7d
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-09-13 10:10:37 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-09-14 21:55:01 +0000
rtld: more caution when parsing in digest_notes()
Incorrect ELF might have PT_NOTE slightly larger than the needed to
contain all notes, and the PT_NOTE size could be larger than one page.
Then rtld mmaps just the notes bytes to parse. After the last note,
we iterate past the mapped region trying to read the Elf_Note header.
This was found in wild.
Require full elf note to fit into the [start_note, end_note) region to
continue the parsing. Check it in stages, first verifying the Elf_Note
header structure fits, to be able to read the name and data length.
After that, check the whole note against limit.
Reported and tested by: makc
Reviewed by: emaste
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D59635
---
libexec/rtld-elf/rtld.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 469488d094f9..850e017a404d 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -1785,14 +1785,19 @@ digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path)
void
digest_notes(Obj_Entry *obj, Elf_Addr note_start, Elf_Addr note_end)
{
- const Elf_Note *note;
+ const Elf_Note *note, *next_note;
const char *note_name;
uintptr_t p;
- for (note = (const Elf_Note *)note_start; (Elf_Addr)note < note_end;
- note = (const Elf_Note *)((const char *)(note + 1) +
- roundup2(note->n_namesz, sizeof(Elf32_Addr)) +
- roundup2(note->n_descsz, sizeof(Elf32_Addr)))) {
+ for (note = (const Elf_Note *)note_start;; note = next_note) {
+ if ((Elf_Addr)note + sizeof(Elf_Note) > note_end)
+ break;
+ next_note = (const Elf_Note *)((const char *)(note + 1) +
+ roundup2(note->n_namesz, sizeof(Elf32_Addr)) +
+ roundup2(note->n_descsz, sizeof(Elf32_Addr)));
+ if ((Elf_Addr)next_note > note_end)
+ break;
+
if (arch_digest_note(obj, note))
continue;