An Elf descriptor has a "zero" class until the Ehdr is created.
NO_BITS section data only has a size, not a buf.
* libelf/elf_strptr.c (elf_strptr): Return NULL and set libelf
errno to ELF_E_WRONG_ORDER_EHDR, when class is 0. Don't use
Elf_Data with NULL d_buf.
A user-created data block can have a size but a NULL d_buf
(elf_newdata does not validate d_buf). The data-list path of
elf_strptr passed such a NULL buffer to validate_str, which
dereferences it and crashes.
Check d_buf != NULL before validate_str and fail with
ELF_E_INVALID_DATA.
* libelf/elf_strptr.c (elf_strptr): Check d_buf is not NULL.
Signed-off-by: Mark Wielaard <[email protected]>
---
libelf/elf_strptr.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/libelf/elf_strptr.c b/libelf/elf_strptr.c
index f0a7d7ea07af..56a48ad5866d 100644
--- a/libelf/elf_strptr.c
+++ b/libelf/elf_strptr.c
@@ -66,6 +66,13 @@ elf_strptr (Elf *elf, size_t idx, size_t offset)
return NULL;
}
+ /* Class is set from the Ehdr. */
+ if (elf->class == 0)
+ {
+ __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+ return NULL;
+ }
+
rwlock_rdlock (elf->lock);
char *result = NULL;
@@ -231,6 +238,13 @@ elf_strptr (Elf *elf, size_t idx, size_t offset)
if (offset >= (size_t) dl->data.d.d_off
&& offset < dl->data.d.d_off + dl->data.d.d_size)
{
+ /* NO_BITS section data only has a size, not a buf. */
+ if (unlikely (dl->data.d.d_buf == NULL))
+ {
+ __libelf_seterrno (ELF_E_INVALID_DATA);
+ break;
+ }
+
/* Make sure the string is NUL terminated. Start from
the end, which very likely is a NUL char. */
if (likely (validate_str ((char *) dl->data.d.d_buf,
--
2.56.0