Hello,
the issue has been reported by Gianni Kapetanakis month ago [1]. It took
several emails to figure out relayd(8) exists after hosts got disabled
by 'relayctl host dis ...'
The thing is that relayd(8) relies on pf(4) to create persistent
tables (PFR_TFLAG_PERSIST) as relayd requests that:
47 void
48 init_tables(struct relayd *env)
49 {
...
62 TAILQ_FOREACH(rdr, env->sc_rdrs, entry) {
63 if (strlcpy(tables[i].pfrt_anchor, RELAYD_ANCHOR "/",
64 sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
65 goto toolong;
66 if (strlcat(tables[i].pfrt_anchor, rdr->conf.name,
67 sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
68 goto toolong;
69 if (strlcpy(tables[i].pfrt_name, rdr->conf.name,
70 sizeof(tables[i].pfrt_name)) >=
71 sizeof(tables[i].pfrt_name))
72 goto toolong;
73 tables[i].pfrt_flags |= PFR_TFLAG_PERSIST;
74 i++;
75 }
unfortunately it's not the case as further investigation revealed [2].
the issue can be easily reproduced by pfctl(8) which also creates
persistent tables on behalf of command line:
pfctl -t foo -T add ...
command above always asks pf(4) to create persistent table, however
pf(4) does not honor persistent flag when <foo> table exists already.
One can verify that using commands as follows:
## create 'referenced' table only (table exists but has no active flag)
# echo 'pass from in <foo> to any' |pfctl -f -
# pfctl -sT -vg
----r-- foo
# create instance of table <foo> using command line:
# pfctl -t foo -T add 192.168.1.0/24
1/1 addresses added.
# pfctl -sT -vg
--a-r-- foo
## create instance of table <bar>, note the table will get 'p' flag
# pfctl -t bar -T add 192.168.10.0/24
1 table created.
1/1 addresses added.
# pfctl -sT -vg
-pa---- bar
--a-r-- foo
one-liner change to sys/net/pf_table.c fixes that it also works for Gianni
Kapetanakis. I'm also adding tests to regress/sys/net/pf_table/Makefile
to cover it.
On system which runs current the test fails with error as follows:
pfctl -a regress/ttest -t instance -T add 192.168.1.0/24
1/1 addresses added.
pfctl -a regress/ttest -sT -vg | diff table-persist.out -
1c1
< -pa-r-- instance regress/ttest
---
> --a-r-- instance regress/ttest
*** Error 1 in . (Makefile:96 'flags')
FAILED
the failure is expected on system without patch. On system with
patch applied all tests do pass.
OK to commit?
thanks and
regards
sashan
[1] https://marc.info/?t=168811270400005&r=1&w=2
[2] https://marc.info/?l=openbsd-bugs&m=168868165801905&w=2
--------8<---------------8<---------------8<------------------8<--------
diff --git a/sys/net/pf_table.c b/sys/net/pf_table.c
index 6f23a6f795d..c862c804f84 100644
--- a/sys/net/pf_table.c
+++ b/sys/net/pf_table.c
@@ -1565,8 +1565,10 @@ pfr_add_tables(struct pfr_table *tbl, int size, int
*nadd, int flags)
xadd++;
} else if (!(flags & PFR_FLAG_DUMMY) &&
!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
- p->pfrkt_nflags = (p->pfrkt_flags &
- ~PFR_TFLAG_USRMASK) | PFR_TFLAG_ACTIVE;
+ p->pfrkt_nflags =
+ (p->pfrkt_flags & ~PFR_TFLAG_USRMASK) |
+ (n->pfrkt_flags & PFR_TFLAG_USRMASK) |
+ PFR_TFLAG_ACTIVE;
SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq);
}
}
diff --git a/regress/sys/net/pf_table/Makefile
b/regress/sys/net/pf_table/Makefile
index a71f0190c73..8911e8a1d35 100644
--- a/regress/sys/net/pf_table/Makefile
+++ b/regress/sys/net/pf_table/Makefile
@@ -1,15 +1,26 @@
# $OpenBSD: Makefile,v 1.3 2017/07/07 23:15:27 bluhm Exp $
-REGRESS_TARGETS= hit miss cleanup
-CLEANFILES= stamp-*
+REGRESS_TARGETS= hit miss cleanup flags
+CLEANFILES= stamp-* \
+ pf-reftab.conf \
+ pf-instance.conf \
+ table-ref.conf \
+ table-pgone.out \
+ table-persist.out \
+ table-ref.out \
+ table-refgone.out
+
stamp-setup:
+ ${SUDO} pfctl -a regress/ttest -Fa
${SUDO} pfctl -qt __regress_tbl -T add -f ${.CURDIR}/table.in
date >$@
cleanup:
rm -f stamp-setup
${SUDO} pfctl -qt __regress_tbl -T kill
+ ${SUDO} pfctl -q -a regress/ttest -Fr
+ ${SUDO} pfctl -q -a regress/ttest -qt instance -T kill
hit: stamp-setup
for i in `cat ${.CURDIR}/table.hit`; do \
@@ -27,6 +38,77 @@ miss: stamp-setup
done; \
exit 0
-.PHONY: hit miss
+#
+# tables <instance> and <reference> are both referenced by rule only
+#
+pf-instab.conf:
+ @echo 'table <instance> { 192.168.1.0/24 }' > $@
+ @echo 'pass in from <instance> to <reference>' >> $@
+
+#
+# table <instance> is active and referred by rule, table <reference>
+# is referenced only.
+pf-reftab.conf:
+ @echo 'pass in from <instance> to <reference>' > $@
+
+#
+# check persistent flag (p) is gone from table <instance> after
+# we load pf-instab.conf. Deals with case when persistent table <instance>
+# exists before pf-instab.conf gets loaded.
+#
+table-pgone.out:
+ @echo '--a-r-- instance regress/ttest' > $@
+ @echo '----r-- reference regress/ttest' >> $@
+
+#
+# verify table <instance> got persistent flag after we
+# run 'pfctl -t instance -T add ...'
+#
+table-persist.out:
+ @echo '-pa-r-- instance regress/ttest' > $@
+ @echo '----r-- reference regress/ttest' >> $@
+
+#
+# verify tables <instance> and <reference> are created on behalf of
+# reference by rule after pf-reftab.conf got loaded.
+#
+table-ref.out:
+ @echo '----r-- instance regress/ttest' > $@
+ @echo '----r-- reference regress/ttest' >> $@
+
+#
+# verify reference to <instance> table (persistent) is gone
+# after rules got flushed
+#
+table-refgone.out:
+ @echo '-pa---- instance regress/ttest' > $@
+
+flags: pf-instab.conf pf-reftab.conf table-pgone.out table-persist.out \
+ table-ref.out table-refgone.out
+ @echo 'loading pf-reftab,conf (tables referenced by rules only)'
+ @cat pf-reftab.conf
+ ${SUDO} pfctl -a regress/ttest -f pf-reftab.conf
+ @echo 'tables <reference> and <instance> should both have ----r--'
+ ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-ref.out -
+ @echo 'creating <instance> table on command line, flags should be:'
+ @cat table-persist.out
+ ${SUDO} pfctl -a regress/ttest -t instance -T add 192.168.1.0/24
+ ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-persist.out -
+ @echo 'flushing rules'
+ ${SUDO} pfctl -a regress/ttest -Fr
+ @echo 'table <reference> should be gone, table <instance> should stay'
+ ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-refgone.out -
+ @echo 'loading pf-instab.conf'
+ @cat pf-instab.conf
+ ${SUDO} pfctl -a regress/ttest -f pf-instab.conf
+ @echo 'table <instance> loses -p- flag:'
+ @cat table-pgone.out
+ ${SUDO} pfctl -a regress/ttest -sT -vg | diff table-pgone.out -
+ @echo 'flusing rules, both tables should be gone'
+ ${SUDO} pfctl -a regress/ttest -Fr
+ @echo 'anchor regress/ttest must be gone'
+ ${SUDO} pfctl -a regress/ttest -sr 2>&1 | grep 'pfctl: Anchor does not
exist'
+
+.PHONY: hit miss flags
.include <bsd.regress.mk>