svn commit: r322328 - head/sys/netipsec

Andrey V. Elsukov ae at FreeBSD.org
Wed Aug 9 19:58:39 UTC 2017


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__));


More information about the svn-src-head mailing list