From b58aa4f06463947e0f899609ab03264e333c67a1 Mon Sep 17 00:00:00 2001
From: Petr Mensik <pemensik@redhat.com>
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