Author: kp
Date: Sun Jul  9 17:56:39 2017
New Revision: 320848
URL: https://svnweb.freebsd.org/changeset/base/320848

Log:
  pf: Fix vnet purging
  
  pf_purge_thread() breaks up the work of iterating all states (in
  pf_purge_expired_states()) and tracks progress in the idx variable.
  
  If multiple vnets exist this results in pf_purge_thread() only calling
  pf_purge_expired_states() for part of the states (the first part of the
  first vnet, second part of the second vnet and so on).
  Combined with the mark-and-sweep approach to cleaning up old rules (in
  V_pf_unlinked_rules) that resulted in pf freeing rules that were still
  referenced by states. This in turn caused panics when pf_state_expires()
  encounters that state and attempts to access the rule.
  
  We need to track the progress per vnet, not globally, so idx is moved
  into a per-vnet V_pf_purge_idx.
  
  PR:           219251
  Sponsored by: Hackathon Essen 2017

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

Modified: head/sys/netpfil/pf/pf.c
==============================================================================
--- head/sys/netpfil/pf/pf.c    Sun Jul  9 17:05:48 2017        (r320847)
+++ head/sys/netpfil/pf/pf.c    Sun Jul  9 17:56:39 2017        (r320848)
@@ -132,6 +132,9 @@ VNET_DEFINE(int,                     pf_tcp_iss_off);
 VNET_DECLARE(int,                       pf_vnet_active);
 #define        V_pf_vnet_active                 VNET(pf_vnet_active)
 
+static VNET_DEFINE(uint32_t, pf_purge_idx);
+#define V_pf_purge_idx VNET(pf_purge_idx)
+
 /*
  * Queue for pf_intr() sends.
  */
@@ -1427,7 +1430,6 @@ void
 pf_purge_thread(void *unused __unused)
 {
        VNET_ITERATOR_DECL(vnet_iter);
-       u_int idx = 0;
 
        sx_xlock(&pf_end_lock);
        while (pf_end_threads == 0) {
@@ -1448,14 +1450,15 @@ pf_purge_thread(void *unused __unused)
                         *  Process 1/interval fraction of the state
                         * table every run.
                         */
-                       idx = pf_purge_expired_states(idx, pf_hashmask /
+                       V_pf_purge_idx =
+                           pf_purge_expired_states(V_pf_purge_idx, pf_hashmask 
/
                            (V_pf_default_rule.timeout[PFTM_INTERVAL] * 10));
 
                        /*
                         * Purge other expired types every
                         * PFTM_INTERVAL seconds.
                         */
-                       if (idx == 0) {
+                       if (V_pf_purge_idx == 0) {
                                /*
                                 * Order is important:
                                 * - states and src nodes reference rules
_______________________________________________
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