From b58aa4f06463947e0f899609ab03264e333c67a1 Mon Sep 17 00:00:00 2001 From: Petr Mensik Date: Wed, 21 Apr 2021 12:39:17 +0200 Subject: [PATCH] Accept responses also from non-last bound interface Partial backport of upstream commit 74d4fcd756a85bc1823232ea74334f7ccfb9d5d2, smaller part of CVE-2021-3448 fix. --- src/forward.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/forward.c b/src/forward.c index a0b1f1d..ec2de6f 100644 --- a/src/forward.c +++ b/src/forward.c @@ -2228,6 +2228,8 @@ struct frec *get_new_frec(time_t now, int *wait, int force) static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash) { struct frec *f; + struct server *s; + int type; for(f = daemon->frec_list; f; f = f->next) if (f->sentto && f->new_id == id && @@ -2240,9 +2242,21 @@ static struct frec *lookup_frec(unsigned short id, int fd, int family, void *has if (family == AF_INET6 && f->rfd6 && f->rfd6->fd == fd) return f; - /* sent to upstream from bound socket. */ - if (f->sentto->sfd && f->sentto->sfd->fd == fd) - return f; + /* Sent to upstream from socket associated with a server. + Note we have to iterate over all the possible servers, since they may + have different bound sockets. */ + type = f->sentto->flags & SERV_TYPE; + s = f->sentto; + do { + if ((type == (s->flags & SERV_TYPE)) && + (type != SERV_HAS_DOMAIN || + (s->domain && hostname_isequal(f->sentto->domain, s->domain))) && + !(s->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)) && + s->sfd && s->sfd->fd == fd) + return f; + + s = s->next ? s->next : daemon->servers; + } while (s != f->sentto); } return NULL; -- 2.26.3