Re: oss-fuzz

2020-01-06 Thread Matthias Maennich via elfutils-devel

Hi everyone!

On Thu, Dec 26, 2019 at 11:50:48PM +0100, Mark Wielaard wrote:

Hi Berkeley,

On Mon, Dec 23, 2019 at 08:06:54AM +0200, Berkeley Churchill wrote:

Great, thanks for the feedback!

One of my first tasks will be to support llvm/clang builds.  I've seen some
prior discussion on what's needed for that, but if you have any extra tips
I'll take them.  I'll be sure to create a build target for the fuzzers so
they can be run standalone.


clang is slightly inconvenient because it doesn't implement various
GNU C extensions. We even have a configure check for them now so it is
clear what we require from a C/gnu99 compiler:
https://sourceware.org/git/?p=elfutils.git;a=blob;f=configure.ac;hb=HEAD#l98

In theory when clang support that, everything should just compile.

There have been some attempts to rewrite some source code to get clang
to accept it:
https://sourceware.org/git/?p=elfutils.git&a=search&h=HEAD&st=commit&s=clang

But there is just too much code clang simply doesn't parse.

I don't know how much work there is left to get clang to accept
everything. But Matthias (CCed) said he got somewhat further on irc
once. Maybe he can share his patches.


The version of elfutils that I maintain is incomplete, but sufficient to
run libabigail on top of it and to compile everything with clang. So, my
local modifications can be summarized as:
- I use a different build system (similar to Bazel (https://bazel.build/)
- build a completely static version
- disable some warnings to build with -Werror otherwise
- Use a static config.h that is created with
   ./configure --without-lzma --without-bzlib and modified to
  - #undef HAVE_FALLTHROUGH
  - #undef HAVE_GCC_STRUCT

The source code itself is not modified for building with clang. Though I
adopted some patches from the DTS branch to build a version with builtin
ebl backends. A comparable series is merged upstream for the next
release as far as I can see.

The most tricky to address are the nested function definitions. It is
not entirely clear to me how to resolve these without completely messing
up the existing code. Most of them would end up as macro or factored out
function that takes a lot of arguments. I did not find the time to work
on a solution that is suitable upstream.



A simpler approach would be to see if oss-fuzz really needs clang at
all. As far as I know the only thing needed is a compiler supporting
inserting tracing calls into every basic block and/or comparison
operations and linking to some (C++) library that intercepts those. gcc
can do that with -fsanitize-coverage=trace-pc and/or
-fsanitize-coverage=trace-cmp (which I believe is command line
compatible with what clang uses).


I run a fuzzing project against libabigail which indirectly also fuzzes
some parts of elfutils (the subset I am compiling). So far, I did not
come across a finding in elfutils. But again, I am covering only a very
small subset of the code.

Cheers,
Matthias



Cheers,

Mark


On Mon, Dec 23, 2019 at 3:12 AM Mark Wielaard  wrote:

> Hi Berkeley,
>
> On Fri, 2019-12-20 at 17:21 +0200, Berkeley Churchill wrote:
> > Any interest in integrating with oss-fuzz?  It's a google project
> > that supports open source projects by fuzzing. It allows Google to
> > find and report bugs, especially security bugs, to the project.
> > I'm willing to work on writing fuzzers and performing the integration,
> > if this would be welcome by the maintainers.   Thoughts?
>
> Certainly interested. I have been running afl-fuzz on various utilities
> and test cases. That has found lots of issues. But it isn't very
> structured. And it often needs to go through a completely valid ELF
> file before fuzzing the more interesting data structures inside it.
>
> The only request I would have is that if the fuzzer targets are added
> to elfutils itself then they should also be made to work locally. So
> someone could also use them with e.g. afl-fuzz or some other fuzzing
> framework, or simply as extra testcase.
>
> Please also see:
> https://sourceware.org/git/?p=elfutils.git;f=CONTRIBUTING;hb=HEAD
>
> Cheers,
>
> Mark
>


[PATCH] libelf: decompress: ensure zlib resource cleanup

2020-03-15 Thread Matthias Maennich via Elfutils-devel
__libelf_decompress would only cleanup zlib resources via inflateEnd()
in case inflating was successful, but would leak memory if not. Fix this
by calling inflateEnd() in the error case as well.

Fixes: 272018bba1f2 ("libelf: Add elf_compress and elf_compress_gnu.")
Signed-off-by: Matthias Maennich 
---
 libelf/elf_compress.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
index 244467b5e3ae..beb1834bbbd7 100644
--- a/libelf/elf_compress.c
+++ b/libelf/elf_compress.c
@@ -257,6 +257,7 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t 
size_out)
   if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
 {
   free (buf_out);
+  inflateEnd(&z);
   __libelf_seterrno (ELF_E_DECOMPRESS_ERROR);
   return NULL;
 }
-- 
2.25.1.481.gfbce0eb801-goog



Re: [PATCH] libelf: decompress: ensure zlib resource cleanup

2020-03-15 Thread Matthias Maennich via Elfutils-devel

Hi Mark!

Thanks for the quick response!

On Mon, Mar 16, 2020 at 12:10:51AM +0100, Mark Wielaard wrote:

Hi Matthias,

On Sun, 2020-03-15 at 23:03 +0100, Matthias Maennich via Elfutils-devel wrote:

__libelf_decompress would only cleanup zlib resources via inflateEnd()
in case inflating was successful, but would leak memory if not. Fix this
by calling inflateEnd() in the error case as well.

Fixes: 272018bba1f2 ("libelf: Add elf_compress and elf_compress_gnu.")
Signed-off-by: Matthias Maennich 
---
 libelf/elf_compress.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
index 244467b5e3ae..beb1834bbbd7 100644
--- a/libelf/elf_compress.c
+++ b/libelf/elf_compress.c
@@ -257,6 +257,7 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t 
size_out)
   if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
 {
   free (buf_out);
+  inflateEnd(&z);
   __libelf_seterrno (ELF_E_DECOMPRESS_ERROR);
   return NULL;
 }


This looks correct at first sight, but...

Just before this hunk we do:

 if (likely (zrc == Z_OK))
   zrc = inflateEnd (&z);

So, zrc can be !Z_OK because the earlier inflateEnd() failed, which
might cause it to call inflateEnd() twice (which might be fine, I
dunno). Should we maybe ignore the error if inflateEnd() and just call
it unconditionally before (ignoring its return code)?

So, replace:
 if (... Z_OK) zrc = inflateEnd (&z);
with unconditionally ending the stream:
 (void)inflateEnd(&z);



I prefer your variant (and it was my first version of the patch)
independently from what comes below.

Having said that: I looked up what inflateEnd() does and the worst that
could happen is returning an error that we anyway ignore. So, duplicate
calls are not an issue. Also, for the compression part we call
deflateEnd() via a macro in the same duplicate fashion. Hence I
consistently used the same pattern for inflateEnd(). And last, I wanted
to keep that existing error handling. OTOH, projects (including the
example code of zlib [1]) usually just unconditionally call inflateEnd()
ignoring any error codes. So, your call :-)

Cheers,
Matthias

[1] https://zlib.net/zlib_how.html


What do you think?

Cheers,

Mark


[PATCH v2] libelf: {de,}compress: ensure zlib resource cleanup

2020-03-20 Thread Matthias Maennich via Elfutils-devel
__libelf_decompress would only cleanup zlib resources via inflateEnd()
in case inflating was successful, but would leak memory if not. Fix this
by calling inflateEnd() unconditionally.

__libelf_decompress did this all the time already, but called
deflateEnd() twice. That is not a (known) issue, but can be cleaned up
by ensuring all error paths use 'return deflate_cleanup' and the success
path calls deflateEnd() only once. Note, the deflate() needs to return
Z_STREAM_END to indicate we are done. Hence change the condition.

Fixes: 272018bba1f2 ("libelf: Add elf_compress and elf_compress_gnu.")
Signed-off-by: Matthias Maennich 
---
 libelf/elf_compress.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
index 244467b5e3ae..b1b896890ff7 100644
--- a/libelf/elf_compress.c
+++ b/libelf/elf_compress.c
@@ -115,7 +115,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
 {
   free (out_buf);
   __libelf_seterrno (ELF_E_COMPRESS_ERROR);
-  return NULL;
+  return deflate_cleanup(NULL, NULL);
 }
 
   Elf_Data cdata;
@@ -197,13 +197,13 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int 
ei_data,
 }
   while (flush != Z_FINISH); /* More data blocks.  */
 
-  zrc = deflateEnd (&z);
-  if (zrc != Z_OK)
+  if (zrc != Z_STREAM_END)
 {
   __libelf_seterrno (ELF_E_COMPRESS_ERROR);
   return deflate_cleanup (NULL, NULL);
 }
 
+  deflateEnd (&z);
   *new_size = used;
   return out_buf;
 }
@@ -251,16 +251,15 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t 
size_out)
}
   zrc = inflateReset (&z);
 }
-  if (likely (zrc == Z_OK))
-zrc = inflateEnd (&z);
 
   if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
 {
   free (buf_out);
+  buf_out = NULL;
   __libelf_seterrno (ELF_E_DECOMPRESS_ERROR);
-  return NULL;
 }
 
+  inflateEnd(&z);
   return buf_out;
 }
 
-- 
2.25.1.696.g5e7596f4ac-goog



Re: [PATCH v2] libelf: {de,}compress: ensure zlib resource cleanup

2020-04-27 Thread Matthias Maennich via Elfutils-devel

On Sat, Apr 25, 2020 at 01:28:33AM +0200, Mark Wielaard wrote:

Hi,

On Fri, Mar 20, 2020 at 12:17:55PM +0100, Matthias Maennich via Elfutils-devel 
wrote:

__libelf_decompress would only cleanup zlib resources via inflateEnd()
in case inflating was successful, but would leak memory if not. Fix this
by calling inflateEnd() unconditionally.

__libelf_decompress did this all the time already, but called
deflateEnd() twice. That is not a (known) issue, but can be cleaned up
by ensuring all error paths use 'return deflate_cleanup' and the success
path calls deflateEnd() only once. Note, the deflate() needs to return
Z_STREAM_END to indicate we are done. Hence change the condition.

Fixes: 272018bba1f2 ("libelf: Add elf_compress and elf_compress_gnu.")
Signed-off-by: Matthias Maennich 
---
 libelf/elf_compress.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
index 244467b5e3ae..b1b896890ff7 100644
--- a/libelf/elf_compress.c
+++ b/libelf/elf_compress.c
@@ -115,7 +115,7 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
 {
   free (out_buf);
   __libelf_seterrno (ELF_E_COMPRESS_ERROR);
-  return NULL;
+  return deflate_cleanup(NULL, NULL);
 }


I was sure this was correct. But we both missed that deflate_cleanup
is a macro that passes out_buf and frees it. So now it is freed
twice... Oops.

GCC10 (not released yet, but already in Fedora 32 beta) has a new
-fanalyzer option which does catch this:

elf_compress.c: In function ‘__libelf_compress’:
elf_compress.c:50:3: error: double-‘free’ of ‘out_buf’ [CWE-415] 
[-Werror=analyzer-double-free]
  50 |   free (out_buf);
 |   ^~
 ‘__libelf_compress’: events 1-10
   |
   |   50 |   free (out_buf);
   |  |   ~~
   |  |   |
   |  |   (10) second ‘free’ here; first ‘free’ was at (9)
   |..
   |   79 |   if (data == NULL)
   |  |  ^
   |  |  |
   |  |  (1) following ‘false’ branch (when ‘data’ is non-NULL)...
   |..
   |   86 |   Elf_Data *next_data = elf_getdata (scn, data);
   |  |   
   |  |   |
   |  |   (2) ...to here
   |..
   |   91 |   *orig_addralign = data->d_align;
   |  |   ~
   |  |   |
   |  |   (3) allocated here
   |..
   |  100 |   if (out_buf == NULL)
   |  |  ~
   |  |  |
   |  |  (4) assuming ‘out_buf’ is non-NULL
   |  |  (5) following ‘false’ branch (when ‘out_buf’ is non-NULL)...
   |..
   |  107 |   size_t used = hsize;
   |  |   ~~
   |  |   |
   |  |   (6) ...to here
   |..
   |  114 |   if (zrc != Z_OK)
   |  |  ~
   |  |  |
   |  |  (7) following ‘true’ branch (when ‘zrc != 0’)...
   |  115 | {
   |  116 |   free (out_buf);
   |  |   
   |  |   |
   |  |   (8) ...to here
   |  |   (9) first ‘free’ here
   |

Fixed by removing the free (out_buf) on line 116 as attached.


Hi Mark!

Thanks for catching and fixing that!



Cheers,

Mark



From 0b2fc95c46dabf85d053b2f0c6aab217b9c5a9b8 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Sat, 25 Apr 2020 01:21:12 +0200
Subject: [PATCH] libelf: Fix double free in __libelf_compress on error path.

In commit 2092865a7e589ff805caa47e69ac9630f34d4f2a
"libelf: {de,}compress: ensure zlib resource cleanup" we added a
call to deflate_cleanup to make sure all resources were freed.
As GCC10 -fanalyzer points out that could cause a double free
of out_buf. Fix by removing the free (out_buf) in __libelf_compress.

Signed-off-by: Mark Wielaard 
---
libelf/ChangeLog  | 4 
libelf/elf_compress.c | 1 -
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 8f79a625..56f5354c 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,7 @@
+2020-04-25  Mark Wielaard  
+
+   * elf_compress.c (__libelf_compress): Remove free (out_buf).
+
2020-03-18  Omar Sandoval  

* elf_getphdrnum.c (__elf_getphdrnum_rdlock): Call
diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
index b1b89689..e5d3d2e0 100644
--- a/libelf/elf_compress.c
+++ b/libelf/elf_compress.c
@@ -113,7 +113,6 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
  int zrc = deflateInit (&z, Z_BEST_COMPRESSION);
  if (zrc != Z_OK)
{
-  free (out_buf);


Maybe add a comment to the deflate_cleanup macro call then?

Cheers,
Matthias


  __libelf_seterrno (ELF_E_COMPRESS_ERROR);
  return deflate_cleanup(NULL, NULL);
}
--
2.26.0





[PATCH] dwfl: fix potential overflow when reporting on kernel modules

2021-11-18 Thread Matthias Maennich via Elfutils-devel
dwfl_linux_kernel_report_modules_ has an outstanding ancient bug when
reading kernel module information from a modules list file. The target
buffer for the module name was sized too small to hold potential values.
Fix that by increasing the value to account for the null termination.

In practice, this unlikely ever happened, but it now got diagnosed by
LLVM as part of a stricter -Wfortify-source implementation [1]:

libdwfl/linux-kernel-modules.c:1019:7: error: 'sscanf' may overflow; 
destination buffer in argument 3 has size 128, but the corresponding specifier 
may require size 129 [-Werror,-Wfortify-source]
modname, &modsz, &modaddr) == 3)

[1] 
https://github.com/llvm/llvm-project/commit/2db66f8d48beeea835cb9a6940e25bc04ab5d941

Suggested-by: Paul Pluzhnikov 
Signed-off-by: Matthias Maennich 
Change-Id: I97b4fcb536273e5ccc4e37b0b9f0f8ffb7487909
---
 libdwfl/linux-kernel-modules.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c
index c0f8dfa4aef2..58c0c417a597 100644
--- a/libdwfl/linux-kernel-modules.c
+++ b/libdwfl/linux-kernel-modules.c
@@ -1008,7 +1008,7 @@ dwfl_linux_kernel_report_modules (Dwfl *dwfl)
   int result = 0;
   Dwarf_Addr modaddr;
   unsigned long int modsz;
-  char modname[128];
+  char modname[128+1];
   char *line = NULL;
   size_t linesz = 0;
   /* We can't just use fscanf here because it's not easy to distinguish \n
-- 
2.34.0.rc2.393.gf8c9666880-goog