sd-bus: fix memstream buffer extraction
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 4 Mar 2021 20:19:02 +0000 (21:19 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 12 Mar 2021 16:35:57 +0000 (17:35 +0100)
I'm getting the following error under valgrind:

==305970== Invalid free() / delete / delete[] / realloc()
==305970==    at 0x483E9F1: free (vg_replace_malloc.c:538)
==305970==    by 0x4012CD: mfree (alloc-util.h:48)
==305970==    by 0x4012EF: freep (alloc-util.h:83)
==305970==    by 0x4017F4: LLVMFuzzerTestOneInput (fuzz-bus-match.c:58)
==305970==    by 0x401A58: main (fuzz-main.c:39)
==305970==  Address 0x59972f0 is 0 bytes inside a block of size 8,192 free'd
==305970==    at 0x483FCE4: realloc (vg_replace_malloc.c:834)
==305970==    by 0x4C986F7: _IO_mem_finish (in /usr/lib64/libc-2.33.so)
==305970==    by 0x4C8F5E0: fclose@@GLIBC_2.2.5 (in /usr/lib64/libc-2.33.so)
==305970==    by 0x49D2CDB: fclose_nointr (fd-util.c:108)
==305970==    by 0x49D2D3D: safe_fclose (fd-util.c:124)
==305970==    by 0x4A4BCCC: fclosep (fd-util.h:41)
==305970==    by 0x4A4E00F: bus_match_to_string (bus-match.c:859)
==305970==    by 0x4016C2: LLVMFuzzerTestOneInput (fuzz-bus-match.c:58)
==305970==    by 0x401A58: main (fuzz-main.c:39)
==305970==  Block was alloc'd at
==305970==    at 0x483FAE5: calloc (vg_replace_malloc.c:760)
==305970==    by 0x4C98787: open_memstream (in /usr/lib64/libc-2.33.so)
==305970==    by 0x49D56D6: open_memstream_unlocked (fileio.c:97)
==305970==    by 0x4A4DEC5: bus_match_to_string (bus-match.c:859)
==305970==    by 0x4016C2: LLVMFuzzerTestOneInput (fuzz-bus-match.c:58)
==305970==    by 0x401A58: main (fuzz-main.c:39)
==305970==

So the fclose() which is called from _cleanup_fclose_ clearly reallocates the
buffer (maybe to save memory?). open_memstream(3) says:

  The locations referred to by these pointers are updated each time the
  stream is flushed (fflush(3)) and  when the stream is closed (fclose(3)).

This seems to mean that we should close the stream first before grabbing the
buffer pointer.

(cherry picked from commit 5963e6f43c4f33d5255ef0fb887cdf382bd51c9e)

src/libsystemd/sd-bus/bus-match.c

index d7da4bf009fcc387c2b9767d3c9de4f81631946a..558fd05aa128e2ec6fcabcd2c0fe82cd3a178b88 100644 (file)
@@ -856,8 +856,7 @@ fail:
 }
 
 char *bus_match_to_string(struct bus_match_component *components, unsigned n_components) {
-        _cleanup_fclose_ FILE *f = NULL;
-        char *buffer = NULL;
+        _cleanup_free_ char *buffer = NULL;
         size_t size = 0;
         unsigned i;
         int r;
@@ -867,7 +866,7 @@ char *bus_match_to_string(struct bus_match_component *components, unsigned n_com
 
         assert(components);
 
-        f = open_memstream_unlocked(&buffer, &size);
+        FILE *f = open_memstream_unlocked(&buffer, &size);
         if (!f)
                 return NULL;
 
@@ -890,10 +889,10 @@ char *bus_match_to_string(struct bus_match_component *components, unsigned n_com
         }
 
         r = fflush_and_check(f);
+        safe_fclose(f);
         if (r < 0)
                 return NULL;
-
-        return buffer;
+        return TAKE_PTR(buffer);
 }
 
 int bus_match_add(