flower: check unused bits in MPLS fields
authorBenjamin LaHaise <benjamin.lahaise@netronome.com>
Mon, 1 May 2017 13:58:40 +0000 (09:58 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 1 May 2017 15:12:21 +0000 (11:12 -0400)
Since several of the the netlink attributes used to configure the flower
classifier's MPLS TC, BOS and Label fields have additional bits which are
unused, check those bits to ensure that they are actually 0 as suggested
by Jamal.

Signed-off-by: Benjamin LaHaise <benjamin.lahaise@netronome.com>
Cc: David Miller <davem@davemloft.net>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Simon Horman <simon.horman@netronome.com>
Cc: Jakub Kicinski <kubakici@wp.pl>
Cc: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sched/cls_flower.c

index 3ecf07666df3a36b7d0b4e0cbca5d7e2935308a5..ca526c0881bd6b4bcff19835befb537f45c6d5ff 100644 (file)
@@ -439,29 +439,39 @@ static void fl_set_key_val(struct nlattr **tb,
                memcpy(mask, nla_data(tb[mask_type]), len);
 }
 
-static void fl_set_key_mpls(struct nlattr **tb,
-                           struct flow_dissector_key_mpls *key_val,
-                           struct flow_dissector_key_mpls *key_mask)
+static int fl_set_key_mpls(struct nlattr **tb,
+                          struct flow_dissector_key_mpls *key_val,
+                          struct flow_dissector_key_mpls *key_mask)
 {
        if (tb[TCA_FLOWER_KEY_MPLS_TTL]) {
                key_val->mpls_ttl = nla_get_u8(tb[TCA_FLOWER_KEY_MPLS_TTL]);
                key_mask->mpls_ttl = MPLS_TTL_MASK;
        }
        if (tb[TCA_FLOWER_KEY_MPLS_BOS]) {
-               key_val->mpls_bos = nla_get_u8(tb[TCA_FLOWER_KEY_MPLS_BOS]);
+               u8 bos = nla_get_u8(tb[TCA_FLOWER_KEY_MPLS_BOS]);
+
+               if (bos & ~MPLS_BOS_MASK)
+                       return -EINVAL;
+               key_val->mpls_bos = bos;
                key_mask->mpls_bos = MPLS_BOS_MASK;
        }
        if (tb[TCA_FLOWER_KEY_MPLS_TC]) {
-               key_val->mpls_tc =
-                       nla_get_u8(tb[TCA_FLOWER_KEY_MPLS_TC]) & MPLS_TC_MASK;
+               u8 tc = nla_get_u8(tb[TCA_FLOWER_KEY_MPLS_TC]);
+
+               if (tc & ~MPLS_TC_MASK)
+                       return -EINVAL;
+               key_val->mpls_tc = tc;
                key_mask->mpls_tc = MPLS_TC_MASK;
        }
        if (tb[TCA_FLOWER_KEY_MPLS_LABEL]) {
-               key_val->mpls_label =
-                       nla_get_u32(tb[TCA_FLOWER_KEY_MPLS_LABEL]) &
-                       MPLS_LABEL_MASK;
+               u32 label = nla_get_u32(tb[TCA_FLOWER_KEY_MPLS_LABEL]);
+
+               if (label & ~MPLS_LABEL_MASK)
+                       return -EINVAL;
+               key_val->mpls_label = label;
                key_mask->mpls_label = MPLS_LABEL_MASK;
        }
+       return 0;
 }
 
 static void fl_set_key_vlan(struct nlattr **tb,
@@ -622,7 +632,9 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
                               sizeof(key->icmp.code));
        } else if (key->basic.n_proto == htons(ETH_P_MPLS_UC) ||
                   key->basic.n_proto == htons(ETH_P_MPLS_MC)) {
-               fl_set_key_mpls(tb, &key->mpls, &mask->mpls);
+               ret = fl_set_key_mpls(tb, &key->mpls, &mask->mpls);
+               if (ret)
+                       return ret;
        } else if (key->basic.n_proto == htons(ETH_P_ARP) ||
                   key->basic.n_proto == htons(ETH_P_RARP)) {
                fl_set_key_val(tb, &key->arp.sip, TCA_FLOWER_KEY_ARP_SIP,