[Bug 260867] [pf][patch] divert-to packets infinitely loop when written back to divert socket
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 260867] [pf][patch] divert-to packets infinitely loop when written back to divert socket"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 260867] [pf][patch] divert-to packets infinitely loop when written back to divert socket"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 260867] [pf][patch] divert-to packets infinitely loop when written back to divert socket"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 260867] [pf][patch] divert-to packets infinitely loop when written back to divert socket"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 260867] pf: divert-to packets infinitely loop when written back to divert socket"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 01 Jan 2022 19:30:57 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=260867
Bug ID: 260867
Summary: [pf][patch] divert-to packets infinitely loop when
written back to divert socket
Product: Base System
Version: CURRENT
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: bugs@FreeBSD.org
Reporter: damjan.jov@gmail.com
Attachment #230608 text/plain
mime type:
Created attachment 230608
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=230608&action=edit
Divert socket test code
On https://forums.freebsd.org/threads/pf-divert-to-loop-problem.81508 the
poster describes how the "divert-to" rule creates packet loops on FreeBSD 12.2,
and I also independently reproduced this bug on 13.0 and 14-CURRENT too.
It can be reproduced with this pf rule:
pass out on em0 divert-to 0.0.0.0 port 2000
while running the attached C code, which binds a divert socket to 0.0.0.0:2000
and reads packets and writes them back unchanged.
Adding some logging to the pf kernel module, I noticed that the
PF_PACKET_LOOPED flag never gets set in the pf_test() function. Checking for
conditions that set it which aren't being met, I think I found out why.
The following one line change fixes the issue for me:
---snip---
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 1686def4626..bd71d338517 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -6496,7 +6496,7 @@ pf_test(int dir, int pflags, struct ifnet *ifp, struct
mbuf **m0, struct inpcb *
if (__predict_false(ip_divert_ptr != NULL) &&
((ipfwtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL)) != NULL)) {
struct ipfw_rule_ref *rr = (struct ipfw_rule_ref *)(ipfwtag+1);
- if (rr->info & IPFW_IS_DIVERT && rr->rulenum == 0) {
+ if (rr->info & IPFW_IS_DIVERT /*&& rr->rulenum == 0*/) {
if (pd.pf_mtag == NULL &&
((pd.pf_mtag = pf_get_mtag(m)) == NULL)) {
action = PF_DROP;
---snip---
Why does that work?
It appears that the "rulenum" field is only written to in this one place:
((struct ipfw_rule_ref *)(ipfwtag+1))->rulenum = dir;
and if "dir" is what I think it is, then as per /usr/include/netpfil/pf/pf.h:
enum { PF_INOUT, PF_IN, PF_OUT };
the 0 in "rr->rulenum == 0" would be PF_INOUT, which packets never are. However
checking for values 1 and 2 instead, didn't seem to fix the issue either. Only
deleting the entire rr->rulenum check seems to fix it.
--
You are receiving this mail because:
You are the assignee for the bug.