[go: up one dir, main page]

aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Grosbein <eugen@FreeBSD.org>2024-08-19 03:34:37 +0000
committerEugene Grosbein <eugen@FreeBSD.org>2024-08-25 06:47:32 +0000
commit41efd8eef313448f63125dd96dfa393f5492edbd (patch)
tree6b1bf5f266bf580c16e079a7531558c8c716f2eb
parent1980b3dfa1f15920ebd268f51813eacd87432f27 (diff)
downloadsrc-stable/12.tar.gz
src-stable/12.zip
libalias: fix subtle racy problem in outside-inside forwardingstable/12
sys/netinet/libalias/alias_db.c has internal static function UseLink() that passes a link to CleanupLink() to verify if the link has expired. If so, UseLink() may return NULL. _FindLinkIn()'s usage of UseLink() is not quite correct. Assume there is "redirect_port udp" configured to forward incoming traffic for specific port to some internal address. Such a rule creates partially specified permanent link. After first such incoming packet libalias creates new fully specified temporary LINK_UDP with default timeout of 60 seconds. Also, in case of low traffic libalias may assign "timestamp" for this new temporary link way in the past because LibAliasTime is updated seldom and can keep old value for tens of seconds, and it will be used for the temporary link. It may happen that next incoming packet for redirected port passed to _FindLinkIn() results in a call to UseLink() that returns NULL due to detected expiration. Immediate return of NULL results in broken translation: either a packet is dropped (deny_incoming mode) or delivered to original destination address instead of internal one. Fix it with additional check for NULL to proceed with a search for original partially specified link. In case of UDP, it also recreates temporary fully specified link with a call to ReLink(). Practical examples are "redirect_port udp" rules for unidirectional SYSLOG protocol (port 514) or some low volume VPN encapsulated in UDP. Thanks to Peter Much for initial analysis and first version of a patch. Reported by: Peter Much <pmc@citylink.dinoex.sub.org> PR: 269770 (cherry picked from commit 8132e959099f0c533f698d8fbc17386f9144432f) (cherry picked from commit e5b85380836378c9e321a4e6d300591e6faf622a)
-rw-r--r--sys/netinet/libalias/alias_db.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c
index ed222c4133d4..e38186d2d696 100644
--- a/sys/netinet/libalias/alias_db.c
+++ b/sys/netinet/libalias/alias_db.c
@@ -870,8 +870,18 @@ _FindLinkIn(struct libalias *la, struct in_addr dst_addr,
case 0:
LIST_FOREACH(lnk, &grp->full, all.in) {
if (lnk->dst_addr.s_addr == dst_addr.s_addr &&
- lnk->dst_port == dst_port)
- return (UseLink(la, lnk));
+ lnk->dst_port == dst_port) {
+ struct alias_link *found;
+
+ found = UseLink(la, lnk);
+ if (found != NULL)
+ return (found);
+ /* link expired */
+ grp = StartPointIn(la, alias_addr, alias_port, link_type, 0);
+ if (grp == NULL)
+ return (NULL);
+ break;
+ }
}
break;
case LINK_UNKNOWN_DEST_PORT: