On Tue, Jul 04, 2017 at 08:10:21PM +0200, Alexander Bluhm wrote:
> Basically we have to remove all malloc(9) from pf or make it MP
> safe.
> 
> login: panic: kernel diagnostic assertion "_kernel_lock_held()" failed: file 
> "/usr/src/sys/kern/kern_malloc.c", line 373
> Stopped at      db_enter+0x7:   leave
>     TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
> *159741  24648      0     0x14000      0x200    0  pfpurge
> db_enter(d0b75a09,f5480e38,d0baed34,f5480e38,d0be3fe0) at db_enter+0x7
> panic(d0baed34,d09c409a,d0a42528,d0a92068,175) at panic+0x71
> __assert(d09c409a,d0a92068,175,d0a42528,b8f) at __assert+0x2e
> free(d7ecdd00,5,50,f5480ecc,d07b3375) at free+0x251
> tag_unref(d0bdc660,1,f5480010,0,0) at tag_unref+0x77
> pf_tag_unref(1,1,f5480f5c,d06dcb38,d0be0908) at pf_tag_unref+0x1a
> pf_free_state(d7329380,ffffffff,40,0,1) at pf_free_state+0x186
> pf_purge_expired_states(2,d0be0908,20,d0a39846,64) at 
> pf_purge_expired_states+0
> x62
> pf_purge_thread(d774e2cc) at pf_purge_thread+0x6e

Convert pf tag malloc(9) and free(9) into a pool to make it MP safe.
While there use TAILQ_FOREACH macro for traversing tags.

ok?

bluhm

Index: net/pf_ioctl.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.317
diff -u -p -r1.317 pf_ioctl.c
--- net/pf_ioctl.c      28 Jun 2017 19:30:24 -0000      1.317
+++ net/pf_ioctl.c      4 Jul 2017 22:22:15 -0000
@@ -84,6 +84,8 @@
 #include <net/if_pfsync.h>
 #endif /* NPFSYNC > 0 */
 
+struct pool             pf_tag_pl;
+
 void                    pfattach(int);
 void                    pf_thread_create(void *);
 int                     pfopen(dev_t, int, int, struct proc *);
@@ -165,6 +167,8 @@ pfattach(int num)
            IPL_SOFTNET, 0, "pfruleitem", NULL);
        pool_init(&pf_queue_pl, sizeof(struct pf_queuespec), 0,
            IPL_SOFTNET, 0, "pfqueue", NULL);
+       pool_init(&pf_tag_pl, sizeof(struct pf_tagname), 0,
+           IPL_SOFTNET, 0, "pftag", NULL);
        hfsc_initialize();
        pfr_initialize();
        pfi_initialize();
@@ -348,16 +352,17 @@ tagname2tag(struct pf_tags *head, char *
         */
 
        /* new entry */
-       if (!TAILQ_EMPTY(head))
-               for (p = TAILQ_FIRST(head); p != NULL &&
-                   p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
-                       new_tagid = p->tag + 1;
+       TAILQ_FOREACH(p, head, entries) {
+               if (p->tag != new_tagid)
+                       break;
+               new_tagid = p->tag + 1;
+       }
 
        if (new_tagid > TAGID_MAX)
                return (0);
 
        /* allocate and fill new struct pf_tagname */
-       tag = malloc(sizeof(*tag), M_RTABLE, M_NOWAIT|M_ZERO);
+       tag = pool_get(&pf_tag_pl, PR_NOWAIT | PR_ZERO);
        if (tag == NULL)
                return (0);
        strlcpy(tag->name, tagname, sizeof(tag->name));
@@ -392,12 +397,11 @@ tag_unref(struct pf_tags *head, u_int16_
        if (tag == 0)
                return;
 
-       for (p = TAILQ_FIRST(head); p != NULL; p = next) {
-               next = TAILQ_NEXT(p, entries);
+       TAILQ_FOREACH_SAFE(p, head, entries, next) {
                if (tag == p->tag) {
                        if (--p->ref == 0) {
                                TAILQ_REMOVE(head, p, entries);
-                               free(p, M_RTABLE, sizeof(*p));
+                               pool_put(&pf_tag_pl, p);
                        }
                        break;
                }

Reply via email to