From nobody Sun Jan 09 23:05:35 2022 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id A64CF1957844; Sun, 9 Jan 2022 23:05:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4JXCH32hkqz4qyT; Sun, 9 Jan 2022 23:05:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 3CA2A1AB11; Sun, 9 Jan 2022 23:05:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 209N5ZXH039152; Sun, 9 Jan 2022 23:05:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 209N5ZsS039151; Sun, 9 Jan 2022 23:05:35 GMT (envelope-from git) Date: Sun, 9 Jan 2022 23:05:35 GMT Message-Id: <202201092305.209N5ZsS039151@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Ed Maste Subject: git: ec746e619578 - stable/13 - Fix fragmented UDP packets handling since rev.360967. List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: emaste X-Git-Repository: src X-Git-Refname: refs/heads/stable/13 X-Git-Reftype: branch X-Git-Commit: ec746e61957840dd26adec945581e66c1b007e99 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1641769535; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=8qSM42G9IrnEob/FejbEy8t0bQqS6lEnNvlAbTwY1c0=; b=dXR9m3aweQZ9MShFWtcVkATf7eQr4NlyUMNVAEFCvngEpr3uvX2eEUOL4LKRHkdG7mKJOB GGFc81p5tDKrRZZ7E8Li2OoREJNeX6F9RBOOL/PIDFctuH4LDXApTzzYoAaAVEzHQ2E2P7 aTuRVhahtLfxQj3MXyGSZHM7dWZLbXno2M/I5ZpKU4Oj6xAirIhokyDZghYrK6TtP8e15r D1oFvCbcd9T83vJsr5y+9N2oDz2Mz8kWrpfBA4ktc4HpE+dQsJN/+8n2EnWlP2de+39qJO Z18lN/VQ7HIVzjCK/pvsFIEWiDjRkYmSnhoLkHQF0hKXQLXmuyAVazg6L6mz8g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1641769535; a=rsa-sha256; cv=none; b=LPLvpdcRWm4oyP41M6TKcJl4zJBYAibUrKAfHDEgOhmou+ETJAIXnUUGPfLBO4QZePyUjq dYTA/LtKSd7578v2UGi6JWSh7E5kIacYtwYEyIpDUbhTCM9mMFlA3v7jkv1ozDaGAW2kBl BTVcRWprJ8n/uOV1kAAUVryX9TZtosg+JRY1nimqfGAxhF5rcZN2uyfmMFqyz5bYvsGhNG 4LARCuWvyg1tQLzvSPtEAhgyGsjdyk8njnBfW8UN9CDmT/9c3RL6LhSqj4OagHfagbPIBU ta6CdW7f3B9NwNfyWXhFHl8s6wWm+lO8DkW1I56tIZrWQN8gm/EpdlPV7/qQzg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by emaste: URL: https://cgit.FreeBSD.org/src/commit/?id=ec746e61957840dd26adec945581e66c1b007e99 commit ec746e61957840dd26adec945581e66c1b007e99 Author: Maxim Sobolev AuthorDate: 2021-10-07 20:41:40 +0000 Commit: Ed Maste CommitDate: 2022-01-09 22:04:56 +0000 Fix fragmented UDP packets handling since rev.360967. Consider IP_MF flag when checking length of the UDP packet to match the declared value. Sponsored by: Sippy Software, Inc. Differential Revision: https://reviews.freebsd.org/D32363 MFC after: 2 weeks (cherry picked from commit 461e6f23db3b9794e6af88b381b066a2c0463d1c) --- sys/netinet/libalias/alias.c | 225 +++++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 105 deletions(-) diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c index 39e9b060623d..37f5bd5a1db1 100644 --- a/sys/netinet/libalias/alias.c +++ b/sys/netinet/libalias/alias.c @@ -721,21 +721,37 @@ ProtoAliasOut(struct libalias *la, struct ip *pip, return (PKT_ALIAS_IGNORED); } +#define MF_ISSET(_pip) (ntohs((_pip)->ip_off) & IP_MF) +#define FRAG_NO_HDR(_pip) (ntohs((_pip)->ip_off) & IP_OFFMASK) + +static struct udphdr * +ValidateUdpLength(struct ip *pip) +{ + struct udphdr *ud; + size_t dlen; + +#ifdef _KERNEL + KASSERT(!FRAG_NO_HDR(pip), ("header-less fragment isn't expected here")); +#endif + dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); + if (dlen < sizeof(struct udphdr)) + return (NULL); + ud = (struct udphdr *)ip_next(pip); + if (!MF_ISSET(pip) && dlen < ntohs(ud->uh_ulen)) + return (NULL); + return (ud); +} + static int UdpAliasIn(struct libalias *la, struct ip *pip) { struct udphdr *ud; struct alias_link *lnk; - size_t dlen; LIBALIAS_LOCK_ASSERT(la); - dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); - if (dlen < sizeof(struct udphdr)) - return (PKT_ALIAS_IGNORED); - - ud = (struct udphdr *)ip_next(pip); - if (dlen < ntohs(ud->uh_ulen)) + ud = ValidateUdpLength(pip); + if (ud == NULL) return (PKT_ALIAS_IGNORED); lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, @@ -828,19 +844,14 @@ UdpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create) u_short proxy_server_port; int proxy_type; int error; - size_t dlen; LIBALIAS_LOCK_ASSERT(la); - /* Return if proxy-only mode is enabled and not proxyrule found.*/ - dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); - if (dlen < sizeof(struct udphdr)) - return (PKT_ALIAS_IGNORED); - - ud = (struct udphdr *)ip_next(pip); - if (dlen < ntohs(ud->uh_ulen)) + ud = ValidateUdpLength(pip); + if (ud == NULL) return (PKT_ALIAS_IGNORED); + /* Return if proxy-only mode is enabled and not proxyrule found.*/ proxy_type = ProxyCheck(la, &proxy_server_address, &proxy_server_port, pip->ip_src, pip->ip_dst, ud->uh_dport, pip->ip_p); if (proxy_type == 0 && (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)) @@ -1339,64 +1350,65 @@ LibAliasInLocked(struct libalias *la, struct ip *pip, int maxpacketsize) goto getout; } + if (FRAG_NO_HDR(pip)) { + iresult = FragmentIn(la, pip->ip_src, pip, pip->ip_id, + &pip->ip_sum); + goto getout; + } + iresult = PKT_ALIAS_IGNORED; - if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { - switch (pip->ip_p) { - case IPPROTO_ICMP: - iresult = IcmpAliasIn(la, pip); - break; - case IPPROTO_UDP: - iresult = UdpAliasIn(la, pip); - break; - case IPPROTO_TCP: - iresult = TcpAliasIn(la, pip); - break; + switch (pip->ip_p) { + case IPPROTO_ICMP: + iresult = IcmpAliasIn(la, pip); + break; + case IPPROTO_UDP: + iresult = UdpAliasIn(la, pip); + break; + case IPPROTO_TCP: + iresult = TcpAliasIn(la, pip); + break; #ifdef _KERNEL - case IPPROTO_SCTP: - iresult = SctpAlias(la, pip, SN_TO_LOCAL); - break; + case IPPROTO_SCTP: + iresult = SctpAlias(la, pip, SN_TO_LOCAL); + break; #endif - case IPPROTO_GRE: { - int error; - struct alias_data ad = { - .lnk = NULL, - .oaddr = NULL, - .aaddr = NULL, - .aport = NULL, - .sport = NULL, - .dport = NULL, - .maxpktsize = 0 - }; - - /* Walk out chain. */ - error = find_handler(IN, IP, la, pip, &ad); - if (error == 0) - iresult = PKT_ALIAS_OK; - else - iresult = ProtoAliasIn(la, pip->ip_src, - pip, pip->ip_p, &pip->ip_sum); - break; - } - default: - iresult = ProtoAliasIn(la, pip->ip_src, pip, - pip->ip_p, &pip->ip_sum); - break; - } + case IPPROTO_GRE: { + int error; + struct alias_data ad = { + .lnk = NULL, + .oaddr = NULL, + .aaddr = NULL, + .aport = NULL, + .sport = NULL, + .dport = NULL, + .maxpktsize = 0 + }; - if (ntohs(pip->ip_off) & IP_MF) { - struct alias_link *lnk; + /* Walk out chain. */ + error = find_handler(IN, IP, la, pip, &ad); + if (error == 0) + iresult = PKT_ALIAS_OK; + else + iresult = ProtoAliasIn(la, pip->ip_src, + pip, pip->ip_p, &pip->ip_sum); + break; + } + default: + iresult = ProtoAliasIn(la, pip->ip_src, pip, + pip->ip_p, &pip->ip_sum); + break; + } - lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); - if (lnk != NULL) { - iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; - SetFragmentAddr(lnk, pip->ip_dst); - } else { - iresult = PKT_ALIAS_ERROR; - } + if (MF_ISSET(pip)) { + struct alias_link *lnk; + + lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); + if (lnk != NULL) { + iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; + SetFragmentAddr(lnk, pip->ip_dst); + } else { + iresult = PKT_ALIAS_ERROR; } - } else { - iresult = FragmentIn(la, pip->ip_src, pip, pip->ip_id, - &pip->ip_sum); } getout: @@ -1492,52 +1504,55 @@ LibAliasOutLocked(struct libalias *la, } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { SetDefaultAliasAddress(la, pip->ip_src); } + + if (FRAG_NO_HDR(pip)) { + iresult = FragmentOut(la, pip, &pip->ip_sum); + goto getout_restore; + } + iresult = PKT_ALIAS_IGNORED; - if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { - switch (pip->ip_p) { - case IPPROTO_ICMP: - iresult = IcmpAliasOut(la, pip, create); - break; - case IPPROTO_UDP: - iresult = UdpAliasOut(la, pip, maxpacketsize, create); - break; - case IPPROTO_TCP: - iresult = TcpAliasOut(la, pip, maxpacketsize, create); - break; + switch (pip->ip_p) { + case IPPROTO_ICMP: + iresult = IcmpAliasOut(la, pip, create); + break; + case IPPROTO_UDP: + iresult = UdpAliasOut(la, pip, maxpacketsize, create); + break; + case IPPROTO_TCP: + iresult = TcpAliasOut(la, pip, maxpacketsize, create); + break; #ifdef _KERNEL - case IPPROTO_SCTP: - iresult = SctpAlias(la, pip, SN_TO_GLOBAL); - break; + case IPPROTO_SCTP: + iresult = SctpAlias(la, pip, SN_TO_GLOBAL); + break; #endif - case IPPROTO_GRE: { - int error; - struct alias_data ad = { - .lnk = NULL, - .oaddr = NULL, - .aaddr = NULL, - .aport = NULL, - .sport = NULL, - .dport = NULL, - .maxpktsize = 0 - }; - /* Walk out chain. */ - error = find_handler(OUT, IP, la, pip, &ad); - if (error == 0) - iresult = PKT_ALIAS_OK; - else - iresult = ProtoAliasOut(la, pip, - pip->ip_dst, pip->ip_p, &pip->ip_sum, create); - break; - } - default: + case IPPROTO_GRE: { + int error; + struct alias_data ad = { + .lnk = NULL, + .oaddr = NULL, + .aaddr = NULL, + .aport = NULL, + .sport = NULL, + .dport = NULL, + .maxpktsize = 0 + }; + /* Walk out chain. */ + error = find_handler(OUT, IP, la, pip, &ad); + if (error == 0) + iresult = PKT_ALIAS_OK; + else iresult = ProtoAliasOut(la, pip, pip->ip_dst, pip->ip_p, &pip->ip_sum, create); - break; + break; } - } else { - iresult = FragmentOut(la, pip, &pip->ip_sum); + default: + iresult = ProtoAliasOut(la, pip, + pip->ip_dst, pip->ip_p, &pip->ip_sum, create); + break; } +getout_restore: SetDefaultAliasAddress(la, addr_save); getout: return (iresult);