net/sched: flower: Fix null pointer dereference when run tc vlan command
authorJianbo Liu <jianbol@mellanox.com>
Mon, 9 Jul 2018 02:26:20 +0000 (02:26 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 12 Jul 2018 05:48:13 +0000 (22:48 -0700)
Zahari issued tc vlan command without setting vlan_ethtype, which will
crash kernel. To avoid this, we must check tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]
is not null before use it.
Also we don't need to dump vlan_ethtype or cvlan_ethtype in this case.

Fixes: d64efd0926ba ('net/sched: flower: Add supprt for matching on QinQ vlan headers')
Signed-off-by: Jianbo Liu <jianbol@mellanox.com>
Reported-by: Zahari Doychev <zahari.doychev@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/cls_flower.c

index 487a152a852cd092fdce123a0623b726ba00aaa4..8b2474293db190f44c6644b4f7f837e8e614bb05 100644 (file)
@@ -605,20 +605,22 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
                                        TCA_FLOWER_KEY_VLAN_PRIO, &key->vlan,
                                        &mask->vlan);
 
-                       ethertype = nla_get_be16(tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]);
-                       if (eth_type_vlan(ethertype)) {
-                               fl_set_key_vlan(tb, ethertype,
-                                               TCA_FLOWER_KEY_CVLAN_ID,
-                                               TCA_FLOWER_KEY_CVLAN_PRIO,
-                                               &key->cvlan, &mask->cvlan);
-                               fl_set_key_val(tb, &key->basic.n_proto,
-                                              TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
-                                              &mask->basic.n_proto,
-                                              TCA_FLOWER_UNSPEC,
-                                              sizeof(key->basic.n_proto));
-                       } else {
-                               key->basic.n_proto = ethertype;
-                               mask->basic.n_proto = cpu_to_be16(~0);
+                       if (tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]) {
+                               ethertype = nla_get_be16(tb[TCA_FLOWER_KEY_VLAN_ETH_TYPE]);
+                               if (eth_type_vlan(ethertype)) {
+                                       fl_set_key_vlan(tb, ethertype,
+                                                       TCA_FLOWER_KEY_CVLAN_ID,
+                                                       TCA_FLOWER_KEY_CVLAN_PRIO,
+                                                       &key->cvlan, &mask->cvlan);
+                                       fl_set_key_val(tb, &key->basic.n_proto,
+                                                      TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+                                                      &mask->basic.n_proto,
+                                                      TCA_FLOWER_UNSPEC,
+                                                      sizeof(key->basic.n_proto));
+                               } else {
+                                       key->basic.n_proto = ethertype;
+                                       mask->basic.n_proto = cpu_to_be16(~0);
+                               }
                        }
                } else {
                        key->basic.n_proto = ethertype;
@@ -1344,14 +1346,16 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, void *fh,
                         key->cvlan.vlan_tpid)))
                goto nla_put_failure;
 
-       if (mask->cvlan.vlan_tpid) {
-               if (nla_put_be16(skb, TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
-                                key->basic.n_proto))
-                       goto nla_put_failure;
-       } else if (mask->vlan.vlan_tpid) {
-               if (nla_put_be16(skb, TCA_FLOWER_KEY_VLAN_ETH_TYPE,
-                                key->basic.n_proto))
-                       goto nla_put_failure;
+       if (mask->basic.n_proto) {
+               if (mask->cvlan.vlan_tpid) {
+                       if (nla_put_be16(skb, TCA_FLOWER_KEY_CVLAN_ETH_TYPE,
+                                        key->basic.n_proto))
+                               goto nla_put_failure;
+               } else if (mask->vlan.vlan_tpid) {
+                       if (nla_put_be16(skb, TCA_FLOWER_KEY_VLAN_ETH_TYPE,
+                                        key->basic.n_proto))
+                               goto nla_put_failure;
+               }
        }
 
        if ((key->basic.n_proto == htons(ETH_P_IP) ||