untrusted comment: verify with openbsd-68-base.pub
RWQZj25CSG5R2h2AGMzW77ehLQAmUMuMfxwBbMALGW43S937DiqWV4YTWvqWEIHB7NmbHZDfjPpZCIVh4afuNvR+eCfUolvrEwc=

OpenBSD 6.8 errata 005, November 10, 2020:

unwind fails to process large DNS replies.

Apply by doing:
   signify -Vep /etc/signify/openbsd-68-base.pub -x 005_unwind.patch.sig \
       -m - | (cd /usr/src && patch -p0)

And then rebuild and install unwind:
   cd /usr/src/sbin/unwind
   make obj
   make
   make install

Index: sbin/unwind/frontend.c
===================================================================
RCS file: /cvs/src/sbin/unwind/frontend.c,v
retrieving revision 1.51
diff -u -p -r1.51 frontend.c
--- sbin/unwind/frontend.c      12 Sep 2020 17:01:03 -0000      1.51
+++ sbin/unwind/frontend.c      5 Nov 2020 10:39:09 -0000
@@ -420,12 +420,14 @@ frontend_dispatch_main(int fd, short eve
void
frontend_dispatch_resolver(int fd, short event, void *bula)
{
-       static struct pending_query     *pq;
+       struct pending_query            *pq;
       struct imsgev                   *iev = bula;
       struct imsgbuf                  *ibuf = &iev->ibuf;
       struct imsg                      imsg;
       struct query_imsg               *query_imsg;
+       struct answer_imsg              *answer_imsg;
       int                              n, shut = 0, chg;
+       uint8_t                         *p;

       if (event & EV_READ) {
               if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
@@ -448,8 +450,6 @@ frontend_dispatch_resolver(int fd, short

               switch (imsg.hdr.type) {
               case IMSG_ANSWER_HEADER:
-                       if (pq != NULL)
-                               fatalx("expected IMSG_ANSWER but got HEADER");
                       if (IMSG_DATA_SIZE(imsg) != sizeof(*query_imsg))
                               fatalx("%s: IMSG_ANSWER_HEADER wrong length: "
                                   "%lu", __func__, IMSG_DATA_SIZE(imsg));
@@ -468,19 +468,35 @@ frontend_dispatch_resolver(int fd, short
                       pq->bogus = query_imsg->bogus;
                       break;
               case IMSG_ANSWER:
-                       if (pq == NULL)
-                               fatalx("IMSG_ANSWER without HEADER");
-
-                       if (pq->answer)
-                               fatal("pq->answer");
-                       if ((pq->answer = malloc(IMSG_DATA_SIZE(imsg))) !=
+                       if (IMSG_DATA_SIZE(imsg) != sizeof(*answer_imsg))
+                               fatalx("%s: IMSG_ANSWER wrong length: "
+                                   "%lu", __func__, IMSG_DATA_SIZE(imsg));
+                       answer_imsg = (struct answer_imsg *)imsg.data;
+                       if ((pq = find_pending_query(answer_imsg->id)) ==
                           NULL) {
-                               pq->answer_len = IMSG_DATA_SIZE(imsg);
-                               memcpy(pq->answer, imsg.data, pq->answer_len);
-                       } else
+                               log_warnx("cannot find pending query %llu",
+                                   answer_imsg->id);
+                               break;
+                       }
+
+                       p = realloc(pq->answer, pq->answer_len +
+                           answer_imsg->len);
+
+                       if (p != NULL) {
+                               pq->answer = p;
+                               memcpy(pq->answer + pq->answer_len,
+                                   answer_imsg->answer, answer_imsg->len);
+                               pq->answer_len += answer_imsg->len;
+                       } else {
+                               free(pq->answer);
+                               pq->answer_len = 0;
+                               pq->answer = NULL;
                               pq->rcode_override = LDNS_RCODE_SERVFAIL;
-                       send_answer(pq);
-                       pq = NULL;
+                               send_answer(pq);
+                               break;
+                       }
+                       if (!answer_imsg->truncated)
+                               send_answer(pq);
                       break;
               case IMSG_CTL_RESOLVER_INFO:
               case IMSG_CTL_AUTOCONF_RESOLVER_INFO:
Index: sbin/unwind/resolver.c
===================================================================
RCS file: /cvs/src/sbin/unwind/resolver.c,v
retrieving revision 1.125
diff -u -p -r1.125 resolver.c
--- sbin/unwind/resolver.c      12 Sep 2020 17:01:03 -0000      1.125
+++ sbin/unwind/resolver.c      5 Nov 2020 10:39:09 -0000
@@ -884,6 +884,7 @@ resolve_done(struct uw_resolver *res, vo
       sldns_buffer            *buf = NULL;
       struct regional         *region = NULL;
       struct query_imsg       *query_imsg;
+       struct answer_imsg       answer_imsg;
       struct running_query    *rq;
       struct timespec          tp, elapsed;
       int64_t                  ms;
@@ -893,6 +894,7 @@ resolve_done(struct uw_resolver *res, vo
       char                     rcode_buf[16];
       char                     qclass_buf[16];
       char                     qtype_buf[16];
+       uint8_t                 *p;

       clock_gettime(CLOCK_MONOTONIC, &tp);

@@ -1014,12 +1016,31 @@ resolve_done(struct uw_resolver *res, vo
       } else
               query_imsg->bogus = 0;

-       resolver_imsg_compose_frontend(IMSG_ANSWER_HEADER, 0, query_imsg,
-           sizeof(*query_imsg));
-
-       /* XXX imsg overflow */
-       resolver_imsg_compose_frontend(IMSG_ANSWER, 0, answer_packet,
-           answer_len);
+       if (resolver_imsg_compose_frontend(IMSG_ANSWER_HEADER, 0, query_imsg,
+           sizeof(*query_imsg)) == -1)
+               fatalx("IMSG_ANSWER_HEADER failed for \"%s %s %s\"",
+                   query_imsg->qname, qclass_buf, qtype_buf);
+
+       answer_imsg.id = query_imsg->id;
+       p = answer_packet;
+       while ((size_t)answer_len > MAX_ANSWER_SIZE) {
+               answer_imsg.truncated = 1;
+               answer_imsg.len = MAX_ANSWER_SIZE;
+               memcpy(&answer_imsg.answer, p, MAX_ANSWER_SIZE);
+               if (resolver_imsg_compose_frontend(IMSG_ANSWER, 0, &answer_imsg,
+                   sizeof(answer_imsg)) == -1)
+                       fatalx("IMSG_ANSWER failed for \"%s %s %s\"",
+                           query_imsg->qname, qclass_buf, qtype_buf);
+               p += MAX_ANSWER_SIZE;
+               answer_len -= MAX_ANSWER_SIZE;
+       }
+       answer_imsg.truncated = 0;
+       answer_imsg.len = answer_len;
+       memcpy(&answer_imsg.answer, p, answer_len);
+       if (resolver_imsg_compose_frontend(IMSG_ANSWER, 0, &answer_imsg,
+           sizeof(answer_imsg)) == -1)
+               fatalx("IMSG_ANSWER failed for \"%s %s %s\"",
+                   query_imsg->qname, qclass_buf, qtype_buf);

       TAILQ_REMOVE(&running_queries, rq, entry);
       evtimer_del(&rq->timer_ev);
Index: sbin/unwind/unwind.c
===================================================================
RCS file: /cvs/src/sbin/unwind/unwind.c,v
retrieving revision 1.49
diff -u -p -r1.49 unwind.c
--- sbin/unwind/unwind.c        12 Sep 2020 17:01:03 -0000      1.49
+++ sbin/unwind/unwind.c        5 Nov 2020 10:39:09 -0000
@@ -726,7 +726,7 @@ void
open_ports(void)
{
       struct addrinfo  hints, *res0;
-       int              udp4sock = -1, udp6sock = -1, error;
+       int              udp4sock = -1, udp6sock = -1, error, bsize = 65535;
       int              opt = 1;

       memset(&hints, 0, sizeof(hints));
@@ -741,6 +741,9 @@ open_ports(void)
                       if (setsockopt(udp4sock, SOL_SOCKET, SO_REUSEADDR,
                           &opt, sizeof(opt)) == -1)
                               log_warn("setting SO_REUSEADDR on socket");
+                       if (setsockopt(udp4sock, SOL_SOCKET, SO_SNDBUF, &bsize,
+                           sizeof(bsize)) == -1)
+                               log_warn("setting SO_SNDBUF on socket");
                       if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen)
                           == -1) {
                               close(udp4sock);
@@ -759,6 +762,9 @@ open_ports(void)
                       if (setsockopt(udp6sock, SOL_SOCKET, SO_REUSEADDR,
                           &opt, sizeof(opt)) == -1)
                               log_warn("setting SO_REUSEADDR on socket");
+                       if (setsockopt(udp6sock, SOL_SOCKET, SO_SNDBUF, &bsize,
+                           sizeof(bsize)) == -1)
+                               log_warn("setting SO_SNDBUF on socket");
                       if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen)
                           == -1) {
                               close(udp6sock);
Index: sbin/unwind/unwind.h
===================================================================
RCS file: /cvs/src/sbin/unwind/unwind.h,v
retrieving revision 1.47
diff -u -p -r1.47 unwind.h
--- sbin/unwind/unwind.h        18 Dec 2019 09:18:27 -0000      1.47
+++ sbin/unwind/unwind.h        5 Nov 2020 10:39:09 -0000
@@ -175,6 +175,15 @@ struct query_imsg {
       struct timespec  tp;
};

+struct answer_imsg {
+#define        MAX_ANSWER_SIZE MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof(uint64_t) - \
+                           2 * sizeof(int)
+       uint64_t         id;
+       int              truncated;
+       int              len;
+       uint8_t          answer[MAX_ANSWER_SIZE];
+};
+
extern uint32_t         cmd_opts;

/* unwind.c */