Thu Aug 27 18:50:25 2020 UTC ()
npf: Make sure to initialize portmap_lock only once.

PR kern/55586


(riastradh)
diff -r1.43 -r1.44 src/sys/net/npf/npf.c
diff -r1.81 -r1.82 src/sys/net/npf/npf_impl.h
diff -r1.5 -r1.6 src/sys/net/npf/npf_portmap.c
diff -r1.18 -r1.19 src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c

cvs diff -r1.43 -r1.44 src/sys/net/npf/npf.c (expand / switch to unified diff)

--- src/sys/net/npf/npf.c 2020/05/30 14:16:56 1.43
+++ src/sys/net/npf/npf.c 2020/08/27 18:50:25 1.44
@@ -23,55 +23,59 @@ @@ -23,55 +23,59 @@
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE. 27 * POSSIBILITY OF SUCH DAMAGE.
28 */ 28 */
29 29
30/* 30/*
31 * NPF main: dynamic load/initialisation and unload routines. 31 * NPF main: dynamic load/initialisation and unload routines.
32 */ 32 */
33 33
34#ifdef _KERNEL 34#ifdef _KERNEL
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.43 2020/05/30 14:16:56 rmind Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.44 2020/08/27 18:50:25 riastradh Exp $");
37 37
38#include <sys/param.h> 38#include <sys/param.h>
39#include <sys/types.h> 39#include <sys/types.h>
40 40
41#include <sys/conf.h> 41#include <sys/conf.h>
42#include <sys/kmem.h> 42#include <sys/kmem.h>
43#include <sys/percpu.h> 43#include <sys/percpu.h>
44#include <sys/xcall.h> 44#include <sys/xcall.h>
45#endif 45#endif
46 46
47#include "npf_impl.h" 47#include "npf_impl.h"
48#include "npf_conn.h" 48#include "npf_conn.h"
49 49
50static __read_mostly npf_t * npf_kernel_ctx = NULL; 50static __read_mostly npf_t * npf_kernel_ctx = NULL;
51 51
52__dso_public int 52__dso_public int
53npfk_sysinit(unsigned nworkers) 53npfk_sysinit(unsigned nworkers)
54{ 54{
 55
55 npf_bpf_sysinit(); 56 npf_bpf_sysinit();
56 npf_tableset_sysinit(); 57 npf_tableset_sysinit();
57 npf_nat_sysinit(); 58 npf_nat_sysinit();
 59 npf_portmap_sysinit();
58 return npf_worker_sysinit(nworkers); 60 return npf_worker_sysinit(nworkers);
59} 61}
60 62
61__dso_public void 63__dso_public void
62npfk_sysfini(void) 64npfk_sysfini(void)
63{ 65{
 66
64 npf_worker_sysfini(); 67 npf_worker_sysfini();
 68 npf_portmap_sysfini();
65 npf_nat_sysfini(); 69 npf_nat_sysfini();
66 npf_tableset_sysfini(); 70 npf_tableset_sysfini();
67 npf_bpf_sysfini(); 71 npf_bpf_sysfini();
68} 72}
69 73
70__dso_public npf_t * 74__dso_public npf_t *
71npfk_create(int flags, const npf_mbufops_t *mbufops, 75npfk_create(int flags, const npf_mbufops_t *mbufops,
72 const npf_ifops_t *ifops, void *arg) 76 const npf_ifops_t *ifops, void *arg)
73{ 77{
74 npf_t *npf; 78 npf_t *npf;
75 79
76 npf = kmem_zalloc(sizeof(npf_t), KM_SLEEP); 80 npf = kmem_zalloc(sizeof(npf_t), KM_SLEEP);
77 npf->ebr = npf_ebr_create(); 81 npf->ebr = npf_ebr_create();

cvs diff -r1.81 -r1.82 src/sys/net/npf/npf_impl.h (expand / switch to unified diff)

--- src/sys/net/npf/npf_impl.h 2020/05/30 14:16:56 1.81
+++ src/sys/net/npf/npf_impl.h 2020/08/27 18:50:25 1.82
@@ -462,26 +462,29 @@ void npf_state_sysinit(npf_t *); @@ -462,26 +462,29 @@ void npf_state_sysinit(npf_t *);
462void npf_state_sysfini(npf_t *); 462void npf_state_sysfini(npf_t *);
463 463
464bool npf_state_init(npf_cache_t *, npf_state_t *); 464bool npf_state_init(npf_cache_t *, npf_state_t *);
465bool npf_state_inspect(npf_cache_t *, npf_state_t *, npf_flow_t); 465bool npf_state_inspect(npf_cache_t *, npf_state_t *, npf_flow_t);
466int npf_state_etime(npf_t *, const npf_state_t *, const int); 466int npf_state_etime(npf_t *, const npf_state_t *, const int);
467void npf_state_destroy(npf_state_t *); 467void npf_state_destroy(npf_state_t *);
468 468
469void npf_state_tcp_sysinit(npf_t *); 469void npf_state_tcp_sysinit(npf_t *);
470void npf_state_tcp_sysfini(npf_t *); 470void npf_state_tcp_sysfini(npf_t *);
471bool npf_state_tcp(npf_cache_t *, npf_state_t *, npf_flow_t); 471bool npf_state_tcp(npf_cache_t *, npf_state_t *, npf_flow_t);
472int npf_state_tcp_timeout(npf_t *, const npf_state_t *); 472int npf_state_tcp_timeout(npf_t *, const npf_state_t *);
473 473
474/* Portmap. */ 474/* Portmap. */
 475void npf_portmap_sysinit(void);
 476void npf_portmap_sysfini(void);
 477
475void npf_portmap_init(npf_t *); 478void npf_portmap_init(npf_t *);
476void npf_portmap_fini(npf_t *); 479void npf_portmap_fini(npf_t *);
477 480
478npf_portmap_t * npf_portmap_create(int, int); 481npf_portmap_t * npf_portmap_create(int, int);
479void npf_portmap_destroy(npf_portmap_t *); 482void npf_portmap_destroy(npf_portmap_t *);
480 483
481in_port_t npf_portmap_get(npf_portmap_t *, int, const npf_addr_t *); 484in_port_t npf_portmap_get(npf_portmap_t *, int, const npf_addr_t *);
482bool npf_portmap_take(npf_portmap_t *, int, const npf_addr_t *, in_port_t); 485bool npf_portmap_take(npf_portmap_t *, int, const npf_addr_t *, in_port_t);
483void npf_portmap_put(npf_portmap_t *, int, const npf_addr_t *, in_port_t); 486void npf_portmap_put(npf_portmap_t *, int, const npf_addr_t *, in_port_t);
484void npf_portmap_flush(npf_portmap_t *); 487void npf_portmap_flush(npf_portmap_t *);
485 488
486/* NAT. */ 489/* NAT. */
487void npf_nat_sysinit(void); 490void npf_nat_sysinit(void);

cvs diff -r1.5 -r1.6 src/sys/net/npf/npf_portmap.c (expand / switch to unified diff)

--- src/sys/net/npf/npf_portmap.c 2020/05/30 14:16:56 1.5
+++ src/sys/net/npf/npf_portmap.c 2020/08/27 18:50:25 1.6
@@ -25,27 +25,27 @@ @@ -25,27 +25,27 @@
25 */ 25 */
26 26
27/* 27/*
28 * NPF port map mechanism. 28 * NPF port map mechanism.
29 * 29 *
30 * The port map is a bitmap used to track TCP/UDP ports used for 30 * The port map is a bitmap used to track TCP/UDP ports used for
31 * translation. Port maps are per IP addresses, therefore multiple 31 * translation. Port maps are per IP addresses, therefore multiple
32 * NAT policies operating on the same IP address will share the 32 * NAT policies operating on the same IP address will share the
33 * same port map. 33 * same port map.
34 */ 34 */
35 35
36#ifdef _KERNEL 36#ifdef _KERNEL
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: npf_portmap.c,v 1.5 2020/05/30 14:16:56 rmind Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: npf_portmap.c,v 1.6 2020/08/27 18:50:25 riastradh Exp $");
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/types.h> 41#include <sys/types.h>
42 42
43#include <sys/atomic.h> 43#include <sys/atomic.h>
44#include <sys/bitops.h> 44#include <sys/bitops.h>
45#include <sys/kmem.h> 45#include <sys/kmem.h>
46#include <sys/mutex.h> 46#include <sys/mutex.h>
47#include <sys/cprng.h> 47#include <sys/cprng.h>
48#include <sys/thmap.h> 48#include <sys/thmap.h>
49#endif 49#endif
50 50
51#include "npf_impl.h" 51#include "npf_impl.h"
@@ -99,54 +99,70 @@ typedef struct bitmap { @@ -99,54 +99,70 @@ typedef struct bitmap {
99#define NPF_PORTMAP_MAXPORT 65535 99#define NPF_PORTMAP_MAXPORT 65535
100 100
101struct npf_portmap { 101struct npf_portmap {
102 thmap_t * addr_map; 102 thmap_t * addr_map;
103 LIST_HEAD(, bitmap) bitmap_list; 103 LIST_HEAD(, bitmap) bitmap_list;
104 kmutex_t list_lock; 104 kmutex_t list_lock;
105 int min_port; 105 int min_port;
106 int max_port; 106 int max_port;
107}; 107};
108 108
109static kmutex_t portmap_lock; 109static kmutex_t portmap_lock;
110 110
111void 111void
 112npf_portmap_sysinit(void)
 113{
 114
 115 mutex_init(&portmap_lock, MUTEX_DEFAULT, IPL_SOFTNET);
 116 __insn_barrier();
 117}
 118
 119void
 120npf_portmap_sysfini(void)
 121{
 122
 123 mutex_destroy(&portmap_lock);
 124 __insn_barrier();
 125}
 126
 127void
112npf_portmap_init(npf_t *npf) 128npf_portmap_init(npf_t *npf)
113{ 129{
114 npf_portmap_t *pm = npf_portmap_create( 130 npf_portmap_t *pm = npf_portmap_create(
115 NPF_PORTMAP_MINPORT, NPF_PORTMAP_MAXPORT); 131 NPF_PORTMAP_MINPORT, NPF_PORTMAP_MAXPORT);
116 npf_param_t param_map[] = { 132 npf_param_t param_map[] = {
117 { 133 {
118 "portmap.min_port", 134 "portmap.min_port",
119 &pm->min_port, 135 &pm->min_port,
120 .default_val = NPF_PORTMAP_MINPORT, 136 .default_val = NPF_PORTMAP_MINPORT,
121 .min = 1024, .max = 65535 137 .min = 1024, .max = 65535
122 }, 138 },
123 { 139 {
124 "portmap.max_port", 140 "portmap.max_port",
125 &pm->max_port, 141 &pm->max_port,
126 .default_val = 49151, // RFC 6335 142 .default_val = 49151, // RFC 6335
127 .min = 1024, .max = 65535 143 .min = 1024, .max = 65535
128 } 144 }
129 }; 145 };
 146
130 npf_param_register(npf, param_map, __arraycount(param_map)); 147 npf_param_register(npf, param_map, __arraycount(param_map));
131 mutex_init(&portmap_lock, MUTEX_DEFAULT, IPL_SOFTNET); 
132 npf->portmap = pm; 148 npf->portmap = pm;
133} 149}
134 150
135void 151void
136npf_portmap_fini(npf_t *npf) 152npf_portmap_fini(npf_t *npf)
137{ 153{
 154
138 npf_portmap_destroy(npf->portmap); 155 npf_portmap_destroy(npf->portmap);
139 mutex_destroy(&portmap_lock); 
140 npf->portmap = NULL; // diagnostic 156 npf->portmap = NULL; // diagnostic
141} 157}
142 158
143npf_portmap_t * 159npf_portmap_t *
144npf_portmap_create(int min_port, int max_port) 160npf_portmap_create(int min_port, int max_port)
145{ 161{
146 npf_portmap_t *pm; 162 npf_portmap_t *pm;
147 163
148 pm = kmem_zalloc(sizeof(npf_portmap_t), KM_SLEEP); 164 pm = kmem_zalloc(sizeof(npf_portmap_t), KM_SLEEP);
149 mutex_init(&pm->list_lock, MUTEX_DEFAULT, IPL_SOFTNET); 165 mutex_init(&pm->list_lock, MUTEX_DEFAULT, IPL_SOFTNET);
150 pm->addr_map = thmap_create(0, NULL, THMAP_NOCOPY); 166 pm->addr_map = thmap_create(0, NULL, THMAP_NOCOPY);
151 pm->min_port = min_port; 167 pm->min_port = min_port;
152 pm->max_port = max_port; 168 pm->max_port = max_port;

cvs diff -r1.18 -r1.19 src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c (expand / switch to unified diff)

--- src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c 2020/05/30 21:00:31 1.18
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c 2020/08/27 18:50:25 1.19
@@ -61,46 +61,45 @@ void @@ -61,46 +61,45 @@ void
61npf_test_init(int (*pton_func)(int, const char *, void *), 61npf_test_init(int (*pton_func)(int, const char *, void *),
62 const char *(*ntop_func)(int, const void *, char *, socklen_t), 62 const char *(*ntop_func)(int, const void *, char *, socklen_t),
63 long (*rndfunc)(void)) 63 long (*rndfunc)(void))
64{ 64{
65 npf_t *npf; 65 npf_t *npf;
66 66
67#ifdef __NetBSD__ 67#ifdef __NetBSD__
68 // XXX: Workaround for npf_init() 68 // XXX: Workaround for npf_init()
69 if ((npf = npf_getkernctx()) != NULL) { 69 if ((npf = npf_getkernctx()) != NULL) {
70 npf_worker_discharge(npf); 70 npf_worker_discharge(npf);
71 npf_worker_sysfini(); 71 npf_worker_sysfini();
72 } 72 }
73#endif 73#endif
74 npfk_sysinit(0); 
75 npf = npfk_create(0, &npftest_mbufops, &npftest_ifops, NULL); 74 npf = npfk_create(0, &npftest_mbufops, &npftest_ifops, NULL);
76 npfk_thread_register(npf); 75 npfk_thread_register(npf);
77 npf_setkernctx(npf); 76 npf_setkernctx(npf);
78 77
79 npf_state_setsampler(npf_state_sample); 78 npf_state_setsampler(npf_state_sample);
80 _pton_func = pton_func; 79 _pton_func = pton_func;
81 _ntop_func = ntop_func; 80 _ntop_func = ntop_func;
82 _random_func = rndfunc; 81 _random_func = rndfunc;
83 82
84 (void)npf_test_addif(IFNAME_DUMMY, false, false); 83 (void)npf_test_addif(IFNAME_DUMMY, false, false);
85} 84}
86 85
87void 86void
88npf_test_fini(void) 87npf_test_fini(void)
89{ 88{
90 npf_t *npf = npf_getkernctx(); 89 npf_t *npf = npf_getkernctx();
 90
91 npfk_thread_unregister(npf); 91 npfk_thread_unregister(npf);
92 npfk_destroy(npf); 92 npfk_destroy(npf);
93 npfk_sysfini(); 
94} 93}
95 94
96int 95int
97npf_test_load(const void *buf, size_t len, bool verbose) 96npf_test_load(const void *buf, size_t len, bool verbose)
98{ 97{
99 nvlist_t *npf_dict; 98 nvlist_t *npf_dict;
100 npf_error_t error; 99 npf_error_t error;
101 int ret; 100 int ret;
102 101
103 npf_dict = nvlist_unpack(buf, len, 0); 102 npf_dict = nvlist_unpack(buf, len, 0);
104 if (!npf_dict) { 103 if (!npf_dict) {
105 printf("%s: could not unpack the nvlist\n", __func__); 104 printf("%s: could not unpack the nvlist\n", __func__);
106 return EINVAL; 105 return EINVAL;