Author: kp
Date: Sun Apr 26 16:16:39 2020
New Revision: 360344
URL: https://svnweb.freebsd.org/changeset/base/360344

Log:
  pf: Improve input validation
  
  If we pass an anchor name which doesn't exist pfr_table_count() returns
  -1, which leads to an overflow in mallocarray() and thus a panic.
  
  Explicitly check that pfr_table_count() does not return an error.
  
  Reported-by:  syzbot+bd09d55d897d63d5f...@syzkaller.appspotmail.com
  Reviewed by:  melifaro
  MFC after:    1 week
  Differential Revision:        https://reviews.freebsd.org/D24539

Modified:
  head/sys/netpfil/pf/pf_ioctl.c

Modified: head/sys/netpfil/pf/pf_ioctl.c
==============================================================================
--- head/sys/netpfil/pf/pf_ioctl.c      Sun Apr 26 16:13:51 2020        
(r360343)
+++ head/sys/netpfil/pf/pf_ioctl.c      Sun Apr 26 16:16:39 2020        
(r360344)
@@ -3008,7 +3008,8 @@ DIOCCHANGEADDR_error:
        case DIOCRGETTABLES: {
                struct pfioc_table *io = (struct pfioc_table *)addr;
                struct pfr_table *pfrts;
-               size_t totlen, n;
+               size_t totlen;
+               int n;
 
                if (io->pfrio_esize != sizeof(struct pfr_table)) {
                        error = ENODEV;
@@ -3016,6 +3017,11 @@ DIOCCHANGEADDR_error:
                }
                PF_RULES_RLOCK();
                n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
+               if (n < 0) {
+                       PF_RULES_RUNLOCK();
+                       error = EINVAL;
+                       break;
+               }
                io->pfrio_size = min(io->pfrio_size, n);
 
                totlen = io->pfrio_size * sizeof(struct pfr_table);
@@ -3039,7 +3045,8 @@ DIOCCHANGEADDR_error:
        case DIOCRGETTSTATS: {
                struct pfioc_table *io = (struct pfioc_table *)addr;
                struct pfr_tstats *pfrtstats;
-               size_t totlen, n;
+               size_t totlen;
+               int n;
 
                if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
                        error = ENODEV;
@@ -3047,6 +3054,11 @@ DIOCCHANGEADDR_error:
                }
                PF_RULES_WLOCK();
                n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
+               if (n < 0) {
+                       PF_RULES_WUNLOCK();
+                       error = EINVAL;
+                       break;
+               }
                io->pfrio_size = min(io->pfrio_size, n);
 
                totlen = io->pfrio_size * sizeof(struct pfr_tstats);
@@ -3069,7 +3081,8 @@ DIOCCHANGEADDR_error:
        case DIOCRCLRTSTATS: {
                struct pfioc_table *io = (struct pfioc_table *)addr;
                struct pfr_table *pfrts;
-               size_t totlen, n;
+               size_t totlen;
+               int n;
 
                if (io->pfrio_esize != sizeof(struct pfr_table)) {
                        error = ENODEV;
@@ -3078,6 +3091,11 @@ DIOCCHANGEADDR_error:
 
                PF_RULES_WLOCK();
                n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
+               if (n < 0) {
+                       PF_RULES_WUNLOCK();
+                       error = EINVAL;
+                       break;
+               }
                io->pfrio_size = min(io->pfrio_size, n);
 
                totlen = io->pfrio_size * sizeof(struct pfr_table);
@@ -3104,7 +3122,8 @@ DIOCCHANGEADDR_error:
        case DIOCRSETTFLAGS: {
                struct pfioc_table *io = (struct pfioc_table *)addr;
                struct pfr_table *pfrts;
-               size_t totlen, n;
+               size_t totlen;
+               int n;
 
                if (io->pfrio_esize != sizeof(struct pfr_table)) {
                        error = ENODEV;
@@ -3113,6 +3132,12 @@ DIOCCHANGEADDR_error:
 
                PF_RULES_RLOCK();
                n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
+               if (n < 0) {
+                       PF_RULES_RUNLOCK();
+                       error = EINVAL;
+                       break;
+               }
+
                io->pfrio_size = min(io->pfrio_size, n);
                PF_RULES_RUNLOCK();
 
_______________________________________________
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