daemon: fix empty list operator matching every connection - #1641
Open
munzzyy wants to merge 1 commit into
Open
Conversation
listMatch() folds the sub-operators with AND starting from true, so an operator of type list with an empty List returns true and the rule matches every connection. With action allow and precedence, one of those rules short-circuits the rest of the ruleset. Return false when there is nothing to check, like domainsListsCmp() and reListCmp() do when nothing has been loaded.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
listMatch()starts its AND fold attrue:If
o.Listis empty the loop never runs and the function returnstrue. A rule whose operator is typelistwith zero sub-operators matches every connection. Give that ruleallow+precedenceandFindFirstMatch()returns it for the first connection it sees, so nothing below it in the ruleset gets evaluated.Reproduced through the path the GUI uses,
handleActionChangeRule()->Loader.Replace():the scratch test that produced that output (not part of this PR)
That rule would not have survived v1.6.3.
replaceUserRule()unmarshalledOperator.Dataunconditionally for list rules:An empty
Datafailed there withunexpected end of JSON inputand the rule was refused. On HEADDeserialize()blanksDatafor list rules and copies the sub-operators out of the protobuf message instead. When that protobuf list arrives empty, nothing betweenDeserialize()andlistMatch()catches it.So: length check in
listMatch(), returnfalse. That's what the other operators in the file already do.domainsListsCmp()andreListCmp()both returnfalsewhen they have nothing to compare against.Compile()looked like the tidier place for the check, but it doesn't work there.TestNewOperatorListcompiles the operator before assigningopList.List, so the guard fires on a valid rule:Test
TestNewOperatorListEmptyagainst unpatchedoperator.go:With the fix:
Whole package, 27 tests, none failing:
gofmt -l ./rule/andgo vet ./rule/...print exactly what they print on an unmodified tree:loader_test.gounformatted, fourcopies lock valuewarnings inloader.goandrule.go.