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 */