Author: ae
Date: Wed Aug  9 19:58:38 2017
New Revision: 322328
URL: https://svnweb.freebsd.org/changeset/base/322328

Log:
  Make user supplied data checks a bit stricter.
  
  key_msg2sp() is used for parsing data from setsockopt(IP[V6]_IPSEC_POLICY)
  call. This socket option is usually used to configure IPsec bypass for
  socket. Only privileged user can set this socket option.
  The message syntax is described here
        http://www.kame.net/newsletter/20021210/
  
  and our libipsec is usually used to create the correct request.
  Add additional checks:
  * that sadb_x_ipsecrequest_len is not out of bounds of user supplied buffer
  * that src/dst's sa_len is the same
  * that 2*sa_len is not out of bounds of user supplied buffer
  * that 2*sa_len fits into bounds of sadb_x_ipsecrequest
  
  Reported by:  Ilja van Sprundel
  MFC after:    1 week
  Differential Revision:        https://reviews.freebsd.org/D11796

Modified:
  head/sys/netipsec/key.c

Modified: head/sys/netipsec/key.c
==============================================================================
--- head/sys/netipsec/key.c     Wed Aug  9 19:16:54 2017        (r322327)
+++ head/sys/netipsec/key.c     Wed Aug  9 19:58:38 2017        (r322328)
@@ -1403,7 +1403,8 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int
 
                while (tlen > 0) {
                        /* length check */
-                       if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
+                       if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr) ||
+                           xisr->sadb_x_ipsecrequest_len > tlen) {
                                ipseclog((LOG_DEBUG, "%s: invalid ipsecrequest "
                                        "length.\n", __func__));
                                key_freesp(&newsp);
@@ -1517,10 +1518,12 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int
                        if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
                                struct sockaddr *paddr;
 
+                               len = tlen - sizeof(*xisr);
                                paddr = (struct sockaddr *)(xisr + 1);
                                /* validity check */
-                               if (paddr->sa_len
-                                   > sizeof(isr->saidx.src)) {
+                               if (len < sizeof(struct sockaddr) ||
+                                   len < 2 * paddr->sa_len ||
+                                   paddr->sa_len > sizeof(isr->saidx.src)) {
                                        ipseclog((LOG_DEBUG, "%s: invalid "
                                                "request address length.\n",
                                                __func__));
@@ -1528,13 +1531,26 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int
                                        *error = EINVAL;
                                        return NULL;
                                }
+                               /*
+                                * Request length should be enough to keep
+                                * source and destination addresses.
+                                */
+                               if (xisr->sadb_x_ipsecrequest_len <
+                                   sizeof(*xisr) + 2 * paddr->sa_len) {
+                                       ipseclog((LOG_DEBUG, "%s: invalid "
+                                           "ipsecrequest length.\n",
+                                           __func__));
+                                       key_freesp(&newsp);
+                                       *error = EINVAL;
+                                       return (NULL);
+                               }
                                bcopy(paddr, &isr->saidx.src, paddr->sa_len);
                                paddr = (struct sockaddr *)((caddr_t)paddr +
                                    paddr->sa_len);
 
                                /* validity check */
-                               if (paddr->sa_len
-                                   > sizeof(isr->saidx.dst)) {
+                               if (paddr->sa_len !=
+                                   isr->saidx.src.sa.sa_len) {
                                        ipseclog((LOG_DEBUG, "%s: invalid "
                                                "request address length.\n",
                                                __func__));
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to