Hello, One of the teams in Oracle Solaris uses sophisticated naming scheme for PF rulesets. The anchor (ruleset) is identified by something like that:
root/whatever:component:name/some-virtual-instance-long-name/inbound That particular team hit a bug in pfctl, when they were trying to load rule to ruleset specified by anchor above. pfctl(8) on OpenBSD suffers from same problem: echo 'pass'|pfctl -a root/whatever:component:name/some-virtual-instance-long-name/inbound -f - pfctl: pfctl_add_rule: strlcpy the command above bails out in pfctl_rules() function at line 1488: 1481 pf_init_ruleset(rs); 1482 rs->anchor = pf.anchor; 1483 if (strlcpy(pf.anchor->path, anchorname, 1484 sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) 1485 errx(1, "pfctl_add_rule: strlcpy"); 1486 if (strlcpy(pf.anchor->name, anchorname, 1487 sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) 1488 errx(1, "pfctl_add_rule: strlcpy"); 1489 Looks like pfctl confuses anchorname with anchorpath. The anchorname uses 64B buffer. Anchorname is a leaf-path component. If we stick to example above, then anchorname should be '/inbound'. The snippet above has been fixed by change below: + + if ((p = strrchr(anchorname, '/')) != NULL) { + if (!strlen(p)) + err(1, "pfctl_add_rule: bad anchor name %s", + anchorname); + } else + p = anchorname; + + if (strlcpy(pf.anchor->name, p, same code already exists in pfctl_add_rule(). After giving a try I hit a different error: pfctl: pfctl_get_ticket: assertion failed This time game over happened at line 1505: 1496 if ((opts & PF_OPT_NOACTION) == 0) { 1497 /* 1498 * XXX For the time being we need to open transactions for 1499 * the main ruleset before parsing, because tables are still 1500 * loaded at parse time. 1501 */ 1502 if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor)) 1503 ERRX("pfctl_rules"); 1504 pf.astack[0]->ruleset.tticket = 1505 pfctl_get_ticket(t, PF_TRANS_TABLE, anchorname); 1506 } After some more debugging I've arrived to pfctl_load_ruleset(): 1340 pf->anchor = rs->anchor; 1341 1342 if (path[0]) 1343 snprintf(&path[len], PATH_MAX - len, "/%s", pf->anchor->name); 1344 else 1345 snprintf(&path[len], PATH_MAX - len, "%s", pf->anchor->name); I think the else branch should be using ->path instead of ->name. Complete patch is further below. The patch works fine for me (Solaris), still I'm not quite sure it's 100% correct. thanks and regards sasha --------8<---------------8<---------------8<------------------8<-------- diff -r 2f5f0295677c src/sbin/pfctl/pfctl.c --- a/src/sbin/pfctl/pfctl.c Fri Sep 02 15:53:45 2016 +0200 +++ b/src/sbin/pfctl/pfctl.c Fri Sep 02 17:31:05 2016 +0200 @@ -1342,7 +1342,7 @@ pfctl_load_ruleset(struct pfctl *pf, cha if (path[0]) snprintf(&path[len], PATH_MAX - len, "/%s", pf->anchor->name); else - snprintf(&path[len], PATH_MAX - len, "%s", pf->anchor->name); + snprintf(&path[len], PATH_MAX - len, "%s", pf->anchor->path); if (depth) { if (TAILQ_FIRST(rs->rules.active.ptr) != NULL) { @@ -1447,6 +1447,7 @@ pfctl_rules(int dev, char *filename, int struct pfr_table trs; char *path = NULL; int osize; + char *p; bzero(&pf, sizeof(pf)); RB_INIT(&pf_anchors); @@ -1483,7 +1484,15 @@ pfctl_rules(int dev, char *filename, int if (strlcpy(pf.anchor->path, anchorname, sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path)) errx(1, "pfctl_add_rule: strlcpy"); - if (strlcpy(pf.anchor->name, anchorname, + + if ((p = strrchr(anchorname, '/')) != NULL) { + if (!strlen(p)) + err(1, "pfctl_add_rule: bad anchor name %s", + anchorname); + } else + p = anchorname; + + if (strlcpy(pf.anchor->name, p, sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name)) errx(1, "pfctl_add_rule: strlcpy");