We noticed that the ntpd engine process was getting a bit big on some boxes that we'd accidentally cut off from the ntp servers (routing is hard). Reading through the code, I noticed the 'query' member of struct ntp_peer is never freed, which seems to account for the leak.
If you have a server pool in ntpd.conf and it resolves, but ntpd is unable to talk to the servers, it will re-resolve periodically, freeing the old list of peers and creating new ones. To show how slow the leak is, here's the leak report from MALLOC_OPTIONS=D after running for about two hours with four servers from two pools. without diff: Leak report f sum # avg 0x0 9392 128 73 0x889878b920b 512 1 512 0x889878bc8e1 4096 4 1024 0x889878bd065 128 2 64 0x88bc91f0b4b 18280 1 18280 0x88bc926a9ed 65536 1 65536 with diff: Leak report f sum # avg 0x0 6064 16 379 0xbee1253320b 512 1 512 0xbf0265f4b4b 18280 1 18280 0xbf02666e9ed 65536 1 65536 ok? Index: ntp.c =================================================================== RCS file: /cvs/src/usr.sbin/ntpd/ntp.c,v retrieving revision 1.168 diff -u -p -r1.168 ntp.c --- ntp.c 24 Oct 2021 21:24:19 -0000 1.168 +++ ntp.c 23 Mar 2022 10:43:59 -0000 @@ -686,6 +686,7 @@ void peer_remove(struct ntp_peer *p) { TAILQ_REMOVE(&conf->ntp_peers, p, entry); + free(p->query); free(p); peer_cnt--; }