diff options
author | kp <kp@FreeBSD.org> | 2017-03-22 21:18:18 +0000 |
---|---|---|
committer | Luiz Souza <luiz@netgate.com> | 2017-07-17 20:12:49 -0500 |
commit | 8995c199362d57c049f278008c30703cffa626dd (patch) | |
tree | cd4d54c13d8a0e899e438844eead5830f846e66c /sys/netpfil/pf/pf_ioctl.c | |
parent | 29a346c21cd9bf2913cd4e7d0feaf38ccebcab25 (diff) | |
download | FreeBSD-src-8995c199362d57c049f278008c30703cffa626dd.zip FreeBSD-src-8995c199362d57c049f278008c30703cffa626dd.tar.gz |
pf: Fix possible shutdown race
Prevent possible races in the pf_unload() / pf_purge_thread() shutdown
code. Lock the pf_purge_thread() with the new pf_end_lock to prevent
these races.
Use a shared/exclusive lock, as we need to also acquire another sx lock
(VNET_LIST_RLOCK). It's fine for both pf_purge_thread() and pf_unload()
to sleep,
Pointed out by: eri, glebius, jhb
Differential Revision: https://reviews.freebsd.org/D10026
(cherry picked from commit 6f8b05d841a4f034b227995ff8e33cbe42c9cd30)
Diffstat (limited to 'sys/netpfil/pf/pf_ioctl.c')
-rw-r--r-- | sys/netpfil/pf/pf_ioctl.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 9f96c46..8ca8184 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -198,9 +198,11 @@ VNET_DEFINE(int, pf_vnet_active); #define V_pf_vnet_active VNET(pf_vnet_active) int pf_end_threads; +struct proc *pf_purge_proc; struct rwlock pf_rules_lock; struct sx pf_ioctl_lock; +struct sx pf_end_lock; /* pfsync */ pfsync_state_import_t *pfsync_state_import_ptr = NULL; @@ -3780,6 +3782,7 @@ pf_load(void) rw_init(&pf_rules_lock, "pf rulesets"); sx_init(&pf_ioctl_lock, "pf ioctl"); + sx_init(&pf_end_lock, "pf end thread"); pf_mtag_initialize(); @@ -3788,7 +3791,7 @@ pf_load(void) return (ENOMEM); pf_end_threads = 0; - error = kproc_create(pf_purge_thread, NULL, NULL, 0, 0, "pf purge"); + error = kproc_create(pf_purge_thread, NULL, &pf_purge_proc, 0, 0, "pf purge"); if (error != 0) return (error); @@ -3838,11 +3841,13 @@ pf_unload(void) { int error = 0; + sx_xlock(&pf_end_lock); pf_end_threads = 1; while (pf_end_threads < 2) { wakeup_one(pf_purge_thread); - tsleep(pf_purge_thread, 0, "pftmo", 0); + sx_sleep(pf_purge_proc, &pf_end_lock, 0, "pftmo", 0); } + sx_xunlock(&pf_end_lock); if (pf_dev != NULL) destroy_dev(pf_dev); @@ -3851,6 +3856,7 @@ pf_unload(void) rw_destroy(&pf_rules_lock); sx_destroy(&pf_ioctl_lock); + sx_destroy(&pf_end_lock); return (error); } |