netfilter: nf_tables_offload: check FLOW_DISSECTOR_KEY_BASIC in VLAN transfer logic
authorPablo Neira Ayuso <pablo@netfilter.org>
Fri, 18 Jun 2021 23:25:14 +0000 (01:25 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 21 Jun 2021 20:26:19 +0000 (22:26 +0200)
The VLAN transfer logic should actually check for
FLOW_DISSECTOR_KEY_BASIC, not FLOW_DISSECTOR_KEY_CONTROL. Moreover, do
not fallback to case 2) .n_proto is set to 802.1q or 802.1ad, if
FLOW_DISSECTOR_KEY_BASIC is unset.

Fixes: 783003f3bb8a ("netfilter: nftables_offload: special ethertype handling for VLAN")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_tables_offload.c

index ec701b84844fc851ca22d02607e9b902208db130..b58d73a965232c7e4dfa80b6e229fc99f10d8ea8 100644 (file)
@@ -54,15 +54,10 @@ static void nft_flow_rule_transfer_vlan(struct nft_offload_ctx *ctx,
                                        struct nft_flow_rule *flow)
 {
        struct nft_flow_match *match = &flow->match;
-       struct nft_offload_ethertype ethertype;
-
-       if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL) &&
-           match->key.basic.n_proto != htons(ETH_P_8021Q) &&
-           match->key.basic.n_proto != htons(ETH_P_8021AD))
-               return;
-
-       ethertype.value = match->key.basic.n_proto;
-       ethertype.mask = match->mask.basic.n_proto;
+       struct nft_offload_ethertype ethertype = {
+               .value  = match->key.basic.n_proto,
+               .mask   = match->mask.basic.n_proto,
+       };
 
        if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_VLAN) &&
            (match->key.vlan.vlan_tpid == htons(ETH_P_8021Q) ||
@@ -76,7 +71,9 @@ static void nft_flow_rule_transfer_vlan(struct nft_offload_ctx *ctx,
                match->dissector.offset[FLOW_DISSECTOR_KEY_CVLAN] =
                        offsetof(struct nft_flow_key, cvlan);
                match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN);
-       } else {
+       } else if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC) &&
+                  (match->key.basic.n_proto == htons(ETH_P_8021Q) ||
+                   match->key.basic.n_proto == htons(ETH_P_8021AD))) {
                match->key.basic.n_proto = match->key.vlan.vlan_tpid;
                match->mask.basic.n_proto = match->mask.vlan.vlan_tpid;
                match->key.vlan.vlan_tpid = ethertype.value;