1. 19
  1. 13

    On a related note, OpenSSL having their own custom memory allocator back in 2014 was “the final straw” to fork and start LibreSSL (contrary to popular belief that Heartbleed was the trigger).

    https://www.openbsd.org/papers/bsdcan14-libressl/mgp00007.html

    /edit typo

    1. 1

      I thought it was Heartbleed. Thanks for the correction!

    2. 6

      This is definitely a problem with custom allocators, but using a custom allocator and also be leveraged to detect memory bugs. AFL does this:

      Libdislocator is an abusive allocator that can be loaded as a drop-in replacement for the libc implementation via LD_PRELOAD or AFL_LD_PRELOAD.

      It’s in no way AFL-specific, but it should play pretty well with the fuzzer. Basically, when loaded alongside with any dynamically linked binary (source not needed, but static binaries won’t work), it behaves in a way that maximizes the odds of triggering heap corruption issues in the targeted code:

      1. It allocates all buffers so that they are immediately adjacent to a subsequent PROT_NONE page, causing most off-by-one reads and writes to immediately segfault,
      1. It adds a canary immediately below the allocated buffer, to catch writes to negative offsets (won’t catch reads, though),
      1. It sets the memory returned by malloc() to garbage values, improving the odds of crashing when the target accesses uninitialized data,
      1. It sets freed memory to PROT_NONE and does not actually reuse it, causing most use-after-free bugs to segfault right away,
      1. It forces all realloc() calls to return a new address - and sets PROT_NONE on the original block. This catches use-after-realloc bugs,
      1. It checks for calloc() overflows and can cause soft or hard failures of alloc requests past a configurable memory limit (AFL_LD_LIMIT_MB, AFL_LD_HARD_LIMIT).

      https://groups.google.com/forum/#!topic/afl-users/RW4RF6x9aBc

      1. 4

        If we consider that parts of the current Apache code are incompatible with the APR pool debugger then we end up with an unfortunate situation: If a tool like ASAN reports memory safety bugs with the pool debugger we don‘t know if they are real issues or just incompatibilities. If we turn off the pool debugger we won‘t see most of the memory safety bugs.

        This was exactly the situation with the openssl freelists. It had been so long since they’d been turned off the calling code grew to depend on the freelist hiding bugs, at which point turning them off broke the library.

        (Side note: all the apostrophes on the page seem to go the wrong way.)

        1. 3

          Ideally, all these custom allocators would be updated to include ASAN support - you can mark any allocated memory as ‘allocated, but poisoned as far as ASAN is concerned’.

          1. 4

            I’m not sure this is the best way.

            Some of these applications (including Apache) have Valgrind support. Which well, works for Valgrind, which was once the tool to use for these things, but it’s clearly outperformed by ASAN today.

            It seems like a better approach to just have a “make every allocation a real call to malloc” mode, which will work for all current and future tools in that space.

          2. 2

            One could argue from the C language perspective it’s not technically a buffer overflow unless b1 happens to be placed near the end of the memory object allocated from the system.

            It is a violation of the logic the pool allocator implements, which address sanitizer cannot possibly know about – it is entirely possible to imagine a valid program that would allocate an area of memory and write possibly overlapping strings into it.

            Don’t get me wrong, it is a buffer overflow at the program level in this case, and it seems like a good idea to be able to somehow mark the areas that are logical units to be able to catch this.