Re: git: cfa1a1308709 - main - pfctl: fix recrusive printing of ethernet anchors

From: Matteo Riondato <matteo_at_freebsd.org>
Date: Tue, 18 Oct 2022 12:49:54 UTC
On 2022-10-18 at 04:44 EDT, Kristof Provost <kp@FreeBSD.org> wrote:

>On 17 Oct 2022, at 19:37, Matteo Riondato wrote:
>>On 2022-10-07 at 06:13 EDT, Kristof Provost <kp@FreeBSD.org> wrote:
>>>>On 3 Oct 2022, at 18:13, Bryan Drewery wrote:
>>>>>I think there's still a problem here.
>>>>>
>>>>>pfctl -a '*' -sr works pfctl -a 'name/*' -sr does not.
>>>>>
>>>So I’ve looked at this a bit more, and I am now going to back away 
>>>from the whole anchor thing, and try to pretend I didn’t see any  of 
>>>the tentacled horrors that lurk within.
>>>
>>>To give you an idea of the issues, loading the following ruleset:
>>>
>>>	anchor "foo" {
>>>	        anchor "bar" {
>>>	                pass in
>>>	        }
>>>	}
>>>
>>>does exactly what you’d expect:
>>>
>>>	# pfctl -sr -a "*"
>>>	anchor "foo" all {
>>>	  anchor "bar" all {
>>>	    pass in all flags S/SA keep state
>>>	  }
>>>	}
>>>	# pfctl -sr -a "foo/*"
>>>	anchor "bar" all {
>>>	  pass in all flags S/SA keep state
>>>	}
>>>
>>>However, if we `pfctl -Fr` to flush all rules:
>>>
>>>	# pfctl -Fr
>>>	rules cleared
>>>	# pfctl -sr -a "*"
>>>	# pfctl -sr -a "foo/*"
>>>	anchor "bar" all {
>>>	  pass in all flags S/SA keep state
>>>	}
>>>
>>
>>How is one supposed to know which rules are really loaded in this 
>>case?
>>
>>Printing of rules with anchors being broken (I even get a segmentation 
>>fault with 'pfctl -a "*" -sr -vv') makes debugging rulesets very hard.
>>
>`pfctl -a "*" -sr` should always produce the expected results, at least 
>as far as I know.

The last example above clearly shows that `pfctl -a "*"` does *not* 
always produce the expected results: after flushing the rules in the 
root anchor with `pfctl -Fr`, `pfctl -sr -a '*'` does *not* produce the 
expected results, which would have been

anchor "foo" all {
   anchor "bar" all {
	pass in all flags S/SA keep state
	}
}

I'm wondering what gets printed if you load a ruleset such as:

block all
anchor "foo" all {
   pass in all proto udp
   anchor "bar" all {
	pass in all proto tcp flags S/SA keep state
	}
}

Then print it with `pfctl -sr -a '*'`, then do a `pfctl -Fr`, and then 
do another `pfctl -sr -a '*'`, followed by a `pfctl -sr -a "foo/*"`. I 
expect to see, again nothing for the `pfctl -sr -a '*'` after the flush, 
and something like the following for the `pfctl -sr -a "foo/*"`:

anchor "foo" all {
   pass in all proto udp
   anchor "bar" all {
	pass in all proto tcp flags S/SA keep state
	}
}
which at least would (partially?) confirm that `pfctl -Fr` only flushes 
rules in the root anchor.

>I’d be very interested in seeing a test case where that core dumps, 
>because that is indeed very annoying, and might be something I can fix.

I'll try to come up with a minimally reproducible case (it is totally 
reproducible with my settings, but I'd like to give you something 
smaller).

>>Partially, the question I also have is: is printing of rules broken, 
>>or is flushing of rules broken, or a third thing? =)
>>
>To the extent that I currently understand this problem I believe the 
>issue is that we’re not always stepping into child anchors to print 
>them. I believe they do get evaluated when the rules are processed. So 
>it’s the printing that’s broken. The flushing is .. not broken, but may 
>not do what you’d expect. When  we flush we only flush the root anchor, 
>and other anchors can remain.  I think that’s the main source of the 
>strange behaviour I’ve  described.

Assuming that indeed `pfctl -Fr` really only acts on the root anchor, 
what makes me worried is whether rules inside child anchors are really 
evaluated *after* a flush of those in the root anchor with `pfctl -Fr`, 
but checking if they really are evaluated should be an easy test.

Thanks,
Matteo