Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 13 Apr 2018 19:23:01 +0000 (UTC)
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r332486 - stable/11/sys/netpfil/pf
Message-ID:  <201804131923.w3DJN1WL018895@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kp
Date: Fri Apr 13 19:23:01 2018
New Revision: 332486
URL: https://svnweb.freebsd.org/changeset/base/332486

Log:
  MFC r332101:
  
  pf: Improve ioctl validation for DIOCRADDTABLES and DIOCRDELTABLES
  
  The DIOCRADDTABLES and DIOCRDELTABLES ioctls can process a number of
  tables at a time, and as such try to allocate <number of tables> *
  sizeof(struct pfr_table). This multiplication can overflow. Thanks to
  mallocarray() this is not exploitable, but an overflow does panic the
  system.
  
  Arbitrarily limit this to 65535 tables. pfctl only ever processes one
  table at a time, so it presents no issues there.

Modified:
  stable/11/sys/netpfil/pf/pf_ioctl.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netpfil/pf/pf_ioctl.c
==============================================================================
--- stable/11/sys/netpfil/pf/pf_ioctl.c	Fri Apr 13 19:15:31 2018	(r332485)
+++ stable/11/sys/netpfil/pf/pf_ioctl.c	Fri Apr 13 19:23:01 2018	(r332486)
@@ -87,6 +87,8 @@ __FBSDID("$FreeBSD$");
 #include <net/altq/altq.h>
 #endif
 
+#define PF_TABLES_MAX_REQUEST   65535 /* Maximum tables per request. */
+
 static struct pf_pool	*pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
 			    u_int8_t, u_int8_t, u_int8_t);
 
@@ -2523,13 +2525,15 @@ DIOCCHANGEADDR_error:
 			error = ENODEV;
 			break;
 		}
-		totlen = io->pfrio_size * sizeof(struct pfr_table);
-		pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
-		    M_TEMP, M_WAITOK);
-		if (! pfrts) {
+
+		if (io->pfrio_size < 0 || io->pfrio_size > PF_TABLES_MAX_REQUEST) {
 			error = ENOMEM;
 			break;
 		}
+
+		totlen = io->pfrio_size * sizeof(struct pfr_table);
+		pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
+		    M_TEMP, M_WAITOK);
 		error = copyin(io->pfrio_buffer, pfrts, totlen);
 		if (error) {
 			free(pfrts, M_TEMP);
@@ -2552,13 +2556,15 @@ DIOCCHANGEADDR_error:
 			error = ENODEV;
 			break;
 		}
-		totlen = io->pfrio_size * sizeof(struct pfr_table);
-		pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
-		    M_TEMP, M_WAITOK);
-		if (! pfrts) {
+
+		if (io->pfrio_size < 0 || io->pfrio_size > PF_TABLES_MAX_REQUEST) {
 			error = ENOMEM;
 			break;
 		}
+
+		totlen = io->pfrio_size * sizeof(struct pfr_table);
+		pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
+		    M_TEMP, M_WAITOK);
 		error = copyin(io->pfrio_buffer, pfrts, totlen);
 		if (error) {
 			free(pfrts, M_TEMP);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201804131923.w3DJN1WL018895>