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

Reply via email to