Blob Blame History Raw
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