Author: gordon
Date: Tue May 12 16:51:11 2020
New Revision: 360972
URL: https://svnweb.freebsd.org/changeset/base/360972

Log:
  Fix insufficient packet length validation in libalias.
  
  Approved by:  so
  Approved by:  re (implicit)
  Security:     FreeBSD-SA-20:12.libalias
  Security:     CVE-2020-7454

Modified:
  releng/11.3/sys/netinet/libalias/alias.c
  releng/11.4/sys/netinet/libalias/alias.c
  releng/12.1/sys/netinet/libalias/alias.c

Modified: releng/11.3/sys/netinet/libalias/alias.c
==============================================================================
--- releng/11.3/sys/netinet/libalias/alias.c    Tue May 12 16:49:04 2020        
(r360971)
+++ releng/11.3/sys/netinet/libalias/alias.c    Tue May 12 16:51:11 2020        
(r360972)
@@ -439,10 +439,15 @@ fragment contained in ICMP data section */
 static int
 IcmpAliasIn(struct libalias *la, struct ip *pip)
 {
-       int iresult;
        struct icmp *ic;
+       int dlen, iresult;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < ICMP_MINLEN)
+               return (PKT_ALIAS_IGNORED);
+
 /* Return if proxy-only mode is enabled */
        if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
                return (PKT_ALIAS_OK);
@@ -461,6 +466,9 @@ IcmpAliasIn(struct libalias *la, struct ip *pip)
        case ICMP_SOURCEQUENCH:
        case ICMP_TIMXCEED:
        case ICMP_PARAMPROB:
+               if (dlen < ICMP_ADVLENMIN ||
+                   dlen < ICMP_ADVLEN(ic))
+                       return (PKT_ALIAS_IGNORED);
                iresult = IcmpAliasIn2(la, pip);
                break;
        case ICMP_ECHO:
@@ -729,10 +737,17 @@ UdpAliasIn(struct libalias *la, struct ip *pip)
 {
        struct udphdr *ud;
        struct alias_link *lnk;
+       int 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))
+               return (PKT_ALIAS_IGNORED);
 
        lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
            ud->uh_sport, ud->uh_dport,
@@ -821,12 +836,19 @@ UdpAliasOut(struct libalias *la, struct ip *pip, int m
        u_short dest_port;
        u_short proxy_server_port;
        int proxy_type;
-       int error;
+       int dlen, error;
 
        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))
+               return (PKT_ALIAS_IGNORED);
+
        proxy_type = ProxyCheck(la, &proxy_server_address, 
                &proxy_server_port, pip->ip_src, pip->ip_dst, 
                ud->uh_dport, pip->ip_p);
@@ -919,8 +941,13 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
 {
        struct tcphdr *tc;
        struct alias_link *lnk;
+       int dlen;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < sizeof(struct tcphdr))
+               return (PKT_ALIAS_IGNORED);
        tc = (struct tcphdr *)ip_next(pip);
 
        lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
@@ -1039,7 +1066,7 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
 static int
 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
 {
-       int proxy_type, error;
+       int dlen, proxy_type, error;
        u_short dest_port;
        u_short proxy_server_port;
        struct in_addr dest_address;
@@ -1048,6 +1075,10 @@ TcpAliasOut(struct libalias *la, struct ip *pip, int m
        struct alias_link *lnk;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < sizeof(struct tcphdr))
+               return (PKT_ALIAS_IGNORED);
        tc = (struct tcphdr *)ip_next(pip);
 
        if (create)

Modified: releng/11.4/sys/netinet/libalias/alias.c
==============================================================================
--- releng/11.4/sys/netinet/libalias/alias.c    Tue May 12 16:49:04 2020        
(r360971)
+++ releng/11.4/sys/netinet/libalias/alias.c    Tue May 12 16:51:11 2020        
(r360972)
@@ -439,10 +439,15 @@ fragment contained in ICMP data section */
 static int
 IcmpAliasIn(struct libalias *la, struct ip *pip)
 {
-       int iresult;
        struct icmp *ic;
+       int dlen, iresult;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < ICMP_MINLEN)
+               return (PKT_ALIAS_IGNORED);
+
 /* Return if proxy-only mode is enabled */
        if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
                return (PKT_ALIAS_OK);
@@ -461,6 +466,9 @@ IcmpAliasIn(struct libalias *la, struct ip *pip)
        case ICMP_SOURCEQUENCH:
        case ICMP_TIMXCEED:
        case ICMP_PARAMPROB:
+               if (dlen < ICMP_ADVLENMIN ||
+                   dlen < ICMP_ADVLEN(ic))
+                       return (PKT_ALIAS_IGNORED);
                iresult = IcmpAliasIn2(la, pip);
                break;
        case ICMP_ECHO:
@@ -729,10 +737,17 @@ UdpAliasIn(struct libalias *la, struct ip *pip)
 {
        struct udphdr *ud;
        struct alias_link *lnk;
+       int 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))
+               return (PKT_ALIAS_IGNORED);
 
        lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
            ud->uh_sport, ud->uh_dport,
@@ -821,12 +836,19 @@ UdpAliasOut(struct libalias *la, struct ip *pip, int m
        u_short dest_port;
        u_short proxy_server_port;
        int proxy_type;
-       int error;
+       int dlen, error;
 
        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))
+               return (PKT_ALIAS_IGNORED);
+
        proxy_type = ProxyCheck(la, &proxy_server_address, 
                &proxy_server_port, pip->ip_src, pip->ip_dst, 
                ud->uh_dport, pip->ip_p);
@@ -919,8 +941,13 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
 {
        struct tcphdr *tc;
        struct alias_link *lnk;
+       int dlen;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < sizeof(struct tcphdr))
+               return (PKT_ALIAS_IGNORED);
        tc = (struct tcphdr *)ip_next(pip);
 
        lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
@@ -1039,7 +1066,7 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
 static int
 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
 {
-       int proxy_type, error;
+       int dlen, proxy_type, error;
        u_short dest_port;
        u_short proxy_server_port;
        struct in_addr dest_address;
@@ -1048,6 +1075,10 @@ TcpAliasOut(struct libalias *la, struct ip *pip, int m
        struct alias_link *lnk;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < sizeof(struct tcphdr))
+               return (PKT_ALIAS_IGNORED);
        tc = (struct tcphdr *)ip_next(pip);
 
        if (create)

Modified: releng/12.1/sys/netinet/libalias/alias.c
==============================================================================
--- releng/12.1/sys/netinet/libalias/alias.c    Tue May 12 16:49:04 2020        
(r360971)
+++ releng/12.1/sys/netinet/libalias/alias.c    Tue May 12 16:51:11 2020        
(r360972)
@@ -441,10 +441,15 @@ fragment contained in ICMP data section */
 static int
 IcmpAliasIn(struct libalias *la, struct ip *pip)
 {
-       int iresult;
        struct icmp *ic;
+       int dlen, iresult;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < ICMP_MINLEN)
+               return (PKT_ALIAS_IGNORED);
+
 /* Return if proxy-only mode is enabled */
        if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
                return (PKT_ALIAS_OK);
@@ -463,6 +468,9 @@ IcmpAliasIn(struct libalias *la, struct ip *pip)
        case ICMP_SOURCEQUENCH:
        case ICMP_TIMXCEED:
        case ICMP_PARAMPROB:
+               if (dlen < ICMP_ADVLENMIN ||
+                   dlen < ICMP_ADVLEN(ic))
+                       return (PKT_ALIAS_IGNORED);
                iresult = IcmpAliasIn2(la, pip);
                break;
        case ICMP_ECHO:
@@ -731,10 +739,17 @@ UdpAliasIn(struct libalias *la, struct ip *pip)
 {
        struct udphdr *ud;
        struct alias_link *lnk;
+       int 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))
+               return (PKT_ALIAS_IGNORED);
 
        lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
            ud->uh_sport, ud->uh_dport,
@@ -823,12 +838,19 @@ UdpAliasOut(struct libalias *la, struct ip *pip, int m
        u_short dest_port;
        u_short proxy_server_port;
        int proxy_type;
-       int error;
+       int dlen, error;
 
        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))
+               return (PKT_ALIAS_IGNORED);
+
        proxy_type = ProxyCheck(la, &proxy_server_address, 
                &proxy_server_port, pip->ip_src, pip->ip_dst, 
                ud->uh_dport, pip->ip_p);
@@ -921,8 +943,13 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
 {
        struct tcphdr *tc;
        struct alias_link *lnk;
+       int dlen;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < sizeof(struct tcphdr))
+               return (PKT_ALIAS_IGNORED);
        tc = (struct tcphdr *)ip_next(pip);
 
        lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst,
@@ -1041,7 +1068,7 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
 static int
 TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
 {
-       int proxy_type, error;
+       int dlen, proxy_type, error;
        u_short dest_port;
        u_short proxy_server_port;
        struct in_addr dest_address;
@@ -1050,6 +1077,10 @@ TcpAliasOut(struct libalias *la, struct ip *pip, int m
        struct alias_link *lnk;
 
        LIBALIAS_LOCK_ASSERT(la);
+
+       dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+       if (dlen < sizeof(struct tcphdr))
+               return (PKT_ALIAS_IGNORED);
        tc = (struct tcphdr *)ip_next(pip);
 
        if (create)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to