svn commit: r346319 - head/sys/netpfil/pf

Kristof Provost kp at FreeBSD.org
Wed Apr 17 16:42:55 UTC 2019


Author: kp
Date: Wed Apr 17 16:42:54 2019
New Revision: 346319
URL: https://svnweb.freebsd.org/changeset/base/346319

Log:
  pf: Fix panic on invalid DIOCRSETTFLAGS
  
  If during DIOCRSETTFLAGS pfrio_buffer is NULL copyin() will fault, which we're
  not allowed to do with a lock held.
  We must count the number of entries in the table and release the lock during
  copyin(). Only then can we re-acquire the lock. Note that this is safe, because
  pfr_set_tflags() will check if the table and entries exist.
  
  This was discovered by a local syzcaller instance.
  
  MFC after:	1 week
  Event:		Aberdeen hackathon 2019

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

Modified: head/sys/netpfil/pf/pf_ioctl.c
==============================================================================
--- head/sys/netpfil/pf/pf_ioctl.c	Wed Apr 17 16:31:30 2019	(r346318)
+++ head/sys/netpfil/pf/pf_ioctl.c	Wed Apr 17 16:42:54 2019	(r346319)
@@ -3103,24 +3103,24 @@ DIOCCHANGEADDR_error:
 			break;
 		}
 
-		PF_RULES_WLOCK();
+		PF_RULES_RLOCK();
 		n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
 		io->pfrio_size = min(io->pfrio_size, n);
+		PF_RULES_RUNLOCK();
 
 		totlen = io->pfrio_size * sizeof(struct pfr_table);
 		pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
 		    M_TEMP, M_NOWAIT);
 		if (pfrts == NULL) {
 			error = ENOMEM;
-			PF_RULES_WUNLOCK();
 			break;
 		}
 		error = copyin(io->pfrio_buffer, pfrts, totlen);
 		if (error) {
 			free(pfrts, M_TEMP);
-			PF_RULES_WUNLOCK();
 			break;
 		}
+		PF_RULES_WLOCK();
 		error = pfr_set_tflags(pfrts, io->pfrio_size,
 		    io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
 		    &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);


More information about the svn-src-head mailing list