]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/sched/cls_flower.c
flower: check unused bits in MPLS fields
[mirror_ubuntu-artful-kernel.git] / 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,