Hello,

I tested a kernel with WITH_PF_LOCK and NET_TASKQ > 1 and got a
kernel panic during switching between the pf statics inside systat.


I think I found the problem inside pf_ioctl.c, it looks like
the problem was introduced with a "mechanical" patch which
replaced all "breaks;" with "PF_UNLOCK(); break;" This seems
to be wrong in this particular case:

...
        case DIOCGETRULESETS: {

        ...
                        RB_FOREACH(anchor, pf_anchor_node,
                            &ruleset->anchor->children)
                                if (nr++ == pr->nr) {
                                        strlcpy(pr->name, anchor->name,
                                            sizeof(pr->name));
                                        PF_UNLOCK();
                                        break;
                                }
        ...
}

below is a diff to fix it.

 - Joerg


Index: net/pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.344
diff -u -p -r1.344 pf_ioctl.c
--- net/pf_ioctl.c      9 May 2019 14:59:30 -0000       1.344
+++ net/pf_ioctl.c      25 Nov 2019 21:28:41 -0000
@@ -1980,7 +1981,6 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
                                if (anchor->parent == NULL && nr++ == pr->nr) {
                                        strlcpy(pr->name, anchor->name,
                                            sizeof(pr->name));
-                                       PF_UNLOCK();
                                        break;
                                }
                } else {
@@ -1989,13 +1989,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
                                if (nr++ == pr->nr) {
                                        strlcpy(pr->name, anchor->name,
                                            sizeof(pr->name));
-                                       PF_UNLOCK();
                                        break;
                                }
                }
+               PF_UNLOCK();
                if (!pr->name[0])
                        error = EBUSY;
-               PF_UNLOCK();
                break;
        }

Reply via email to