]>
Commit | Line | Data |
---|---|---|
38551f4f GKH |
1 | From foo@baz Sat Jan 26 10:22:50 CET 2019 |
2 | From: Cong Wang <xiyou.wangcong@gmail.com> | |
3 | Date: Fri, 11 Jan 2019 18:55:42 -0800 | |
4 | Subject: net_sched: refetch skb protocol for each filter | |
5 | ||
6 | From: Cong Wang <xiyou.wangcong@gmail.com> | |
7 | ||
8 | [ Upstream commit cd0c4e70fc0ccfa705cdf55efb27519ce9337a26 ] | |
9 | ||
10 | Martin reported a set of filters don't work after changing | |
11 | from reclassify to continue. Looking into the code, it | |
12 | looks like skb protocol is not always fetched for each | |
13 | iteration of the filters. But, as demonstrated by Martin, | |
14 | TC actions could modify skb->protocol, for example act_vlan, | |
15 | this means we have to refetch skb protocol in each iteration, | |
16 | rather than using the one we fetch in the beginning of the loop. | |
17 | ||
18 | This bug is _not_ introduced by commit 3b3ae880266d | |
19 | ("net: sched: consolidate tc_classify{,_compat}"), technically, | |
20 | if act_vlan is the only action that modifies skb protocol, then | |
21 | it is commit c7e2b9689ef8 ("sched: introduce vlan action") which | |
22 | introduced this bug. | |
23 | ||
24 | Reported-by: Martin Olsson <martin.olsson+netdev@sentorsecurity.com> | |
25 | Cc: Jamal Hadi Salim <jhs@mojatatu.com> | |
26 | Cc: Jiri Pirko <jiri@resnulli.us> | |
27 | Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> | |
28 | Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> | |
29 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
30 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
31 | --- | |
32 | net/sched/cls_api.c | 3 +-- | |
33 | 1 file changed, 1 insertion(+), 2 deletions(-) | |
34 | ||
35 | --- a/net/sched/cls_api.c | |
36 | +++ b/net/sched/cls_api.c | |
37 | @@ -1053,7 +1053,6 @@ static int tcf_block_cb_call(struct tcf_ | |
38 | int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp, | |
39 | struct tcf_result *res, bool compat_mode) | |
40 | { | |
41 | - __be16 protocol = tc_skb_protocol(skb); | |
42 | #ifdef CONFIG_NET_CLS_ACT | |
43 | const int max_reclassify_loop = 4; | |
44 | const struct tcf_proto *orig_tp = tp; | |
45 | @@ -1063,6 +1062,7 @@ int tcf_classify(struct sk_buff *skb, co | |
46 | reclassify: | |
47 | #endif | |
48 | for (; tp; tp = rcu_dereference_bh(tp->next)) { | |
49 | + __be16 protocol = tc_skb_protocol(skb); | |
50 | int err; | |
51 | ||
52 | if (tp->protocol != protocol && | |
53 | @@ -1095,7 +1095,6 @@ reset: | |
54 | } | |
55 | ||
56 | tp = first_tp; | |
57 | - protocol = tc_skb_protocol(skb); | |
58 | goto reclassify; | |
59 | #endif | |
60 | } |