<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">Am 30.01.26 um 17:33 schrieb Simon
      Kelley:<br>
    </div>
    <blockquote type="cite"
      cite="mid:88b1f061-f8f2-48be-94fd-9574db1fddf6@thekelleys.org.uk">I
      just sent SIGHUP twice in succession to the dnsmasq process in my
      OpenWRT router, with the new malloc-logging feature enabled.
      <br>
      <br>
      HUP frees a load of configuration and the re-reads it and I
      correlated all the memory freed by the second HUP with what was
      allocated in the first HUP.
      <br>
      <br>
      It's perfect. Every block is freed.
      <br>
      <br>
      <br>
      This is a fairly old installation, so old libraries, etc, but the
      very latest dnsmasq code.
      <br>
      <br>
      The configuration it's re-reading is pretty small.
      <br>
      <br>
      I then tried your technique of hitting dnsmasq hard with many
      HUPs.
      <br>
      <br>
      I had to go up to half a million to see much effect, but I guess
      most of those were dropped since they will have arrived before the
      previous one was cleared.
      <br>
      <br>
      In any case I could see a reproducible rise of a few percent in
      the VSZ of the process each time.
      <br>
      <br>
      What's clear is that the configuration is stored in a _lot_ of
      small allocations, so re-reading a substantial configuration  will
      free a lot of small blocks and then malloc a lot of small blocks.
      <br>
      <br>
      A quick Google produces some complaints about the fragmentation
      performance of musl, which may be significant.
      <br>
      <br>
      Is your installation using musl as the C library, and is it
      possible to build dnsmasq against, say glibc to test?
      <br>
      <br>
      Nearly all of the memory management on dnsmasq that gets hit by
      answering DNS or DHCP requests avoid hammering the malloc system
      by building pools of free data structures that get re-cycled as
      needed. Once the pools have grown to equilibrium size, even a very
      busy server hardly uses the heap. I guess the configuration code
      to use the same policy, but it's a big re-write, and re-reading
      configuration on a sub-second timescale is an unlikely use-case.
      <br>
      <br>
    </blockquote>
    <p>I've built dnsmasq v2.93test2 on Fedora Linux 43 (amd64 aka
      x86_64) with address and undefined behavior sanitizers in GCC and
      with HAVE_DNSSEC, and I am providing three patches (should suit
      git-am) to fix</p>
    <p>* one access past the end of the iovec (reading past the iovcnt
      limit) that triggers AddressSanitizer reproducibly, in
      read_writev()</p>
    <p>* one "variable may be used uninitialized" (I didn't check the
      logic, I just bluntly added = NULL to shut up the compiler) in
      dnssec code</p>
    <p>* one patch that fixes undefined behavior, where base32_decode
      may shift into the sign bit which might wreak havoc on perverse C
      implementations (compiler & processor combination); I didn't
      test if as alternative, making the "oc" an unsigned integer could
      help, because for unsigned integers, wrapping is well-defined, but
      not for signed integers. We can clear the "oc" when we've written
      it.</p>
    <p>I haven't seen a memory leak reported by address sanitizer yet,
      also valgrind in leak-checking mode on FreeBSD didn't holler.</p>
    <p>To reproduce, add #define HAVE_DNSSEC to src/config.h, and change
      these three lines in Makefile - this assumes your debugger
      understands DWARF4 format and the compiler is reasonably
      compatible to GCC. You may need to tweak
      ASAN_OPTIONS=detect_leaks=1 to enable leak checking. Note the leak
      checker availability across operating systems is pretty limited. 
      Systems that don't have it want to forgo that and use a different
      leak checker (valgrind might work).</p>
    <p>
      <blockquote type="cite"><span style="font-family:monospace"><span
            style="color:#18b218;background-color:#ffffff;">CFLAGS
                   = -Wall -W -Og -ggdb3 -gdwarf-4
            -fno-omit-frame-pointer</span><span
            style="color:#000000;background-color:#ffffff;">
          </span><br>
          <span style="color:#18b218;background-color:#ffffff;">LDFLAGS
                  = -fsanitize=address,undefined</span><span
            style="color:#000000;background-color:#ffffff;">
          </span><br>
          <span style="color:#18b218;background-color:#ffffff;">COPTS
                    = -fsanitize=address,undefined</span><br>
        </span></blockquote>
    </p>
  </body>
</html>