openvswitch: Reject ct_state masks for unknown bits
authorJoe Stringer <joestringer@nicira.com>
Tue, 20 Oct 2015 02:18:57 +0000 (19:18 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 22 Oct 2015 02:33:36 +0000 (19:33 -0700)
Currently, 0-bits are generated in ct_state where the bit position is
undefined, and matches are accepted on these bit-positions. If userspace
requests to match the 0-value for this bit then it may expect only a
subset of traffic to match this value, whereas currently all packets
will have this bit set to 0. Fix this by rejecting such masks.

Signed-off-by: Joe Stringer <joestringer@nicira.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/openvswitch/conntrack.h
net/openvswitch/flow_netlink.c

index da8714942c95f73803aa48a157484e898651bc8f..82e0dfc660280cbd24bfd61ac57c0523762b5998 100644 (file)
@@ -35,12 +35,9 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key);
 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb);
 void ovs_ct_free_action(const struct nlattr *a);
 
-static inline bool ovs_ct_state_supported(u32 state)
-{
-       return !(state & ~(OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED |
-                        OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR |
-                        OVS_CS_F_INVALID | OVS_CS_F_TRACKED));
-}
+#define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \
+                          OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | \
+                          OVS_CS_F_INVALID | OVS_CS_F_TRACKED)
 #else
 #include <linux/errno.h>
 
@@ -53,11 +50,6 @@ static inline bool ovs_ct_verify(struct net *net, int attr)
        return false;
 }
 
-static inline bool ovs_ct_state_supported(u32 state)
-{
-       return false;
-}
-
 static inline int ovs_ct_copy_action(struct net *net, const struct nlattr *nla,
                                     const struct sw_flow_key *key,
                                     struct sw_flow_actions **acts, bool log)
@@ -94,5 +86,7 @@ static inline int ovs_ct_put_key(const struct sw_flow_key *key,
 }
 
 static inline void ovs_ct_free_action(const struct nlattr *a) { }
+
+#define CT_SUPPORTED_MASK 0
 #endif /* CONFIG_NF_CONNTRACK */
 #endif /* ovs_conntrack.h */
index 171a691f1c3218ed1a63ac9151c95475ef7fcade..bd710bc374691da3d8ded895d468ff34b23d1cbe 100644 (file)
@@ -816,7 +816,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
            ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
                u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
 
-               if (!is_mask && !ovs_ct_state_supported(ct_state)) {
+               if (ct_state & ~CT_SUPPORTED_MASK) {
                        OVS_NLERR(log, "ct_state flags %08x unsupported",
                                  ct_state);
                        return -EINVAL;
@@ -1099,6 +1099,9 @@ static void nlattr_set(struct nlattr *attr, u8 val,
                } else {
                        memset(nla_data(nla), val, nla_len(nla));
                }
+
+               if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
+                       *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
        }
 }