-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'cls_u32-fix-refcount-leak'
Davide Caratti says: ==================== net/sched: cls_u32: fix refcount leak a refcount leak in the error path of u32_change() has been recently introduced. It can be observed with the following commands: [root@f31 ~]# tc filter replace dev eth0 ingress protocol ip prio 97 \ > u32 match ip src 127.0.0.1/32 indev notexist20 flowid 1:1 action drop RTNETLINK answers: Invalid argument We have an error talking to the kernel [root@f31 ~]# tc filter replace dev eth0 ingress protocol ip prio 98 \ > handle 42:42 u32 divisor 256 Error: cls_u32: Divisor can only be used on a hash table. We have an error talking to the kernel [root@f31 ~]# tc filter replace dev eth0 ingress protocol ip prio 99 \ > u32 ht 47:47 Error: cls_u32: Specified hash table not found. We have an error talking to the kernel they all legitimately return -EINVAL; however, they leave semi-configured filters at eth0 tc ingress: [root@f31 ~]# tc filter show dev eth0 ingress filter protocol ip pref 97 u32 chain 0 filter protocol ip pref 97 u32 chain 0 fh 800: ht divisor 1 filter protocol ip pref 98 u32 chain 0 filter protocol ip pref 98 u32 chain 0 fh 801: ht divisor 1 filter protocol ip pref 99 u32 chain 0 filter protocol ip pref 99 u32 chain 0 fh 802: ht divisor 1 With older kernels, filters were unconditionally considered empty (and thus de-refcounted) on the error path of ->change(). After commit 8b64678 ("net: sched: refactor tp insert/delete for concurrent execution"), filters were considered empty when the walk() function didn't set 'walker.stop' to 1. Finally, with commit 6676d5e ("net: sched: set dedicated tcf_walker flag when tp is empty"), tc filters are considered empty unless the walker function is called with a non-NULL handle. This last change doesn't fit cls_u32 design, because at least the "root hnode" is (almost) always non-NULL, as it's allocated in u32_init(). - patch 1/2 is a proposal to restore the original kernel behavior, where no filter was installed in the error path of u32_change(). - patch 2/2 adds tdc selftests that can be ued to verify the correct behavior of u32 in the error path of ->change(). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Showing
3 changed files
with
230 additions
and
22 deletions.
There are no files selected for viewing
This file contains 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
22 changes: 0 additions & 22 deletions
22
tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
This file contains 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
205 changes: 205 additions & 0 deletions
205
tools/testing/selftests/tc-testing/tc-tests/filters/u32.json
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
[ | ||
{ | ||
"id": "afa9", | ||
"name": "Add u32 with source match", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress" | ||
], | ||
"cmdUnderTest": "$TC filter add dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok", | ||
"expExitCode": "0", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "filter protocol ip pref 1 u32 chain (0[ ]+$|0 fh 800: ht divisor 1|0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1.*match 7f000001/ffffffff at 12)", | ||
"matchCount": "3", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "6aa7", | ||
"name": "Add/Replace u32 with source match and invalid indev", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress" | ||
], | ||
"cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.1/32 indev notexist20 flowid 1:1 action ok", | ||
"expExitCode": "2", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "filter protocol ip pref 1 u32 chain 0", | ||
"matchCount": "0", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "bc4d", | ||
"name": "Replace valid u32 with source match and invalid indev", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress", | ||
"$TC filter add dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.3/32 flowid 1:3 action ok" | ||
], | ||
"cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.2/32 indev notexist20 flowid 1:2 action ok", | ||
"expExitCode": "2", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "filter protocol ip pref 1 u32 chain (0[ ]+$|0 fh 800: ht divisor 1|0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:3.*match 7f000003/ffffffff at 12)", | ||
"matchCount": "3", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "648b", | ||
"name": "Add u32 with custom hash table", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress" | ||
], | ||
"cmdUnderTest": "$TC filter add dev $DEV1 ingress prio 99 handle 42: u32 divisor 256", | ||
"expExitCode": "0", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "pref 99 u32 chain (0[ ]+$|0 fh 42: ht divisor 256|0 fh 800: ht divisor 1)", | ||
"matchCount": "3", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "6658", | ||
"name": "Add/Replace u32 with custom hash table and invalid handle", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress" | ||
], | ||
"cmdUnderTest": "$TC filter replace dev $DEV1 ingress prio 99 handle 42:42 u32 divisor 256", | ||
"expExitCode": "2", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "pref 99 u32 chain 0", | ||
"matchCount": "0", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "9d0a", | ||
"name": "Replace valid u32 with custom hash table and invalid handle", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress", | ||
"$TC filter add dev $DEV1 ingress prio 99 handle 42: u32 divisor 256" | ||
], | ||
"cmdUnderTest": "$TC filter replace dev $DEV1 ingress prio 99 handle 42:42 u32 divisor 128", | ||
"expExitCode": "2", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "pref 99 u32 chain (0[ ]+$|0 fh 42: ht divisor 256|0 fh 800: ht divisor 1)", | ||
"matchCount": "3", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "1644", | ||
"name": "Add u32 filter that links to a custom hash table", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress", | ||
"$TC filter add dev $DEV1 ingress prio 99 handle 43: u32 divisor 256" | ||
], | ||
"cmdUnderTest": "$TC filter add dev $DEV1 ingress protocol ip prio 98 u32 link 43: hashkey mask 0x0000ff00 at 12 match ip src 192.168.0.0/16", | ||
"expExitCode": "0", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "filter protocol ip pref 98 u32 chain (0[ ]+$|0 fh 801: ht divisor 1|0 fh 801::800 order 2048 key ht 801 bkt 0 link 43:.*match c0a80000/ffff0000 at 12.*hash mask 0000ff00 at 12)", | ||
"matchCount": "3", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "74c2", | ||
"name": "Add/Replace u32 filter with invalid hash table id", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress" | ||
], | ||
"cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 20 u32 ht 47:47 action drop", | ||
"expExitCode": "2", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "filter protocol ip pref 20 u32 chain 0", | ||
"matchCount": "0", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
}, | ||
{ | ||
"id": "1fe6", | ||
"name": "Replace valid u32 filter with invalid hash table id", | ||
"category": [ | ||
"filter", | ||
"u32" | ||
], | ||
"plugins": { | ||
"requires": "nsPlugin" | ||
}, | ||
"setup": [ | ||
"$TC qdisc add dev $DEV1 ingress", | ||
"$TC filter add dev $DEV1 ingress protocol ip prio 99 handle 43: u32 divisor 1", | ||
"$TC filter add dev $DEV1 ingress protocol ip prio 98 u32 ht 43: match tcp src 22 FFFF classid 1:3" | ||
], | ||
"cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 98 u32 ht 43:1 match tcp src 23 FFFF classid 1:4", | ||
"expExitCode": "2", | ||
"verifyCmd": "$TC filter show dev $DEV1 ingress", | ||
"matchPattern": "filter protocol ip pref 99 u32 chain (0[ ]+$|0 fh (43|800): ht divisor 1|0 fh 43::800 order 2048 key ht 43 bkt 0 flowid 1:3.*match 00160000/ffff0000 at nexthdr\\+0)", | ||
"matchCount": "4", | ||
"teardown": [ | ||
"$TC qdisc del dev $DEV1 ingress" | ||
] | ||
} | ||
] |