From nobody Sun Jan 09 23:05:44 2022 X-Original-To: dev-commits-src-all@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 CCA581957975; Sun, 9 Jan 2022 23:05:44 +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 4JXCHD2Ldlz4qtj; Sun, 9 Jan 2022 23:05:44 +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 29C6D1A97C; Sun, 9 Jan 2022 23:05:44 +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 209N5i8N039273; Sun, 9 Jan 2022 23:05:44 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 209N5i9f039272; Sun, 9 Jan 2022 23:05:44 GMT (envelope-from git) Date: Sun, 9 Jan 2022 23:05:44 GMT Message-Id: <202201092305.209N5i9f039272@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: 73c5a2566dbb - stable/12 - Fix fragmented UDP packets handling since rev.360967. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@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/12 X-Git-Reftype: branch X-Git-Commit: 73c5a2566dbb3ae57970b203d4de6fcf6088701c Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1641769544; 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=gwRNM2LNis6qCeKH/wX2ZUR5x1tGxIAWRlkb1e4tiYY=; b=BpZHwpL6iOmOeR/cvcMNovg5/bRIXDQB160HClfIEmOzYlcMDcXw9+RJTscdT/SAZaS4iM +0VIpSAFrI4/JYVE+8XoMu+wSWfQdnzo7USEmbIrLcMOndBpF6O+op4rPkNBrEaT1IktFI H9qjFmL4Cf7GDJ9PeNKVVWIxpocfjo8RihAPHaRv3qBZNq+l51iyxpwuu5//9A4e4mjv2a +AT/skLAsdoIikpXTGA0b5DTA5Z2m3FpSRSprZzfw6x65W2UqvWrdVm7tajmRLqUWKZ8tO rRxUWsnDtcSuQQPz2oJg2StiiuUVGV9CNnjR06t+NH4fLPHbMsN+lBOUuDdvww== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1641769544; a=rsa-sha256; cv=none; b=BwO5FNyOQepBxdio/6HOOpWi5CjqVyEhckLTO4AA3UzrdVY0nY8O6MKaralUWhhi8Bx/Gl iNgbcYK3qIGZ1snVnu39gE1GoBsn1+mD3yUA4J4nJl7ZJE70JQ6JAyfHdv8S74tKsF7CWZ C2m4VG33IP/blJDt7rWGW+6SahOil6kN8TN/kw/Tjv+f9HL9m3gJelroOPITGT9H9eSIqM gVwWbTNLtJD3LtxgHw2FSCvuPiqOqpiQuB1V2fox+ICmWt7IqaXeOHdIuMGtPxN5jVM6uk hHSsFOnHxIHj7UlQkfetCXfyUibcpBW5B1n4OXah7pNi7lg2tt6P5/iHPSbmiA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/12 has been updated by emaste: URL: https://cgit.FreeBSD.org/src/commit/?id=73c5a2566dbb3ae57970b203d4de6fcf6088701c commit 73c5a2566dbb3ae57970b203d4de6fcf6088701c Author: Maxim Sobolev AuthorDate: 2021-10-07 20:41:40 +0000 Commit: Ed Maste CommitDate: 2022-01-09 22:06:00 +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 030177eb622d..3436bb62a406 100644 --- a/sys/netinet/libalias/alias.c +++ b/sys/netinet/libalias/alias.c @@ -720,21 +720,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, @@ -827,19 +843,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)) @@ -1338,64 +1349,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: @@ -1491,52 +1503,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);