[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.