On Thu, 2023-09-07 at 06:23 -0700, evv… via monorail via Elfutils-devel
wrote:
> Comment #2 on issue 62071 by evv...@gmail.com: elfutils:fuzz-libdwfl: 
> Null-dereference READ in chunk_compare
> https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=62071#c2
> 
> For some reason the testcase isn't public. I'll report it to OSS-Fuzz.
> 
> I uploaded the test case to GitHub so now it should be
> possible to download it from 
> https://github.com/evverx/elfutils/files/12549426/clusterfuzz-testcase-fuzz-libdwfl-5999675550072832.gz
> 

Thanks. Unfortunately I have still been unable to replicate the crash.
But by reading the code carefully I think I have identified how this
might happen. You must get a somewhat unfortunate out of memory or read
error at precisely the wrong point. The attached patch should fix it.

Cheers,

Mark
From 189a689a73db567f2c2ca30d805665672cae01b4 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <m...@klomp.org>
Date: Thu, 7 Sep 2023 16:14:43 +0200
Subject: [PATCH] libelf: tdelete dummy key if anything goes wrong setting up
 rawchunk

elf_getdata_rawchunk uses a binary search tree cache. If a rawchunk is
not yet in the cache we setup a new entry. But if anything went wrong
setting up the new rawchunk we would leave a NULL key in the
cache. This could blow up the next search. Fix this by removing the
(dummy) key from the cache on any failure.

	* libelf/elf_getdata_rawchunk.c (elf_getdata_rawchunk): Don't
	assign NULL to *found. Call tdelete if anything goes wrong.

Signed-off-by: Mark Wielaard <m...@klomp.org>
---
 libelf/elf_getdata_rawchunk.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c
index cfd40396..05ff329c 100644
--- a/libelf/elf_getdata_rawchunk.c
+++ b/libelf/elf_getdata_rawchunk.c
@@ -107,8 +107,10 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
       goto out;
     }
 
-  /* New entry.  */
-  *found = NULL;
+  /* New entry.  Note that *found will point to the newly inserted
+     (dummy) key.  We'll replace it with a real rawchunk when that is
+     setup.  Make sure to tdelete the dummy key if anything goes
+     wrong.  */
 
   size_t align = __libelf_type_align (elf->class, type);
   if (elf->map_address != NULL)
@@ -134,6 +136,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
       if (rawchunk == NULL)
 	{
 	nomem:
+	  tdelete (&key, &elf->state.elf.rawchunks, &chunk_compare);
 	  __libelf_seterrno (ELF_E_NOMEM);
 	  goto out;
 	}
@@ -144,6 +147,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
 		    != size))
 	{
 	  /* Something went wrong.  */
+	  tdelete (&key, &elf->state.elf.rawchunks, &chunk_compare);
 	  free (rawchunk);
 	  __libelf_seterrno (ELF_E_READ_ERROR);
 	  goto out;
-- 
2.41.0

Reply via email to