summaryrefslogtreecommitdiff
path: root/lib/classifier.c
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-06-13 14:52:59 -0700
committerJarno Rajahalme <jrajahalme@nicira.com>2014-06-13 14:52:59 -0700
commitf0e5aa1107407bbcabb3a816ee40a98b8ba2050c (patch)
tree95d788ec9491764105d25402b92cdc5f4e343d9d /lib/classifier.c
parent197573ac0229b694461d0d98e7e5172c068ab20c (diff)
downloadopenvswitch-f0e5aa1107407bbcabb3a816ee40a98b8ba2050c.tar.gz
lib/classifier: Fix use of uninitialized memory.
When reaching the end of a prefix trie, we checked one bit off the end to the intended data. However, since the trie node in that case has NULLs for both edge links, this did not result in incorrect functionality. Found via check-valgrind. Reported-by: Ben Pfaff <blp@nicira.com> Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/classifier.c')
-rw-r--r--lib/classifier.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/lib/classifier.c b/lib/classifier.c
index c12758f51..f3f4f8eb5 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -178,6 +178,7 @@ static unsigned int trie_lookup(const struct cls_trie *, const struct flow *,
unsigned int *checkbits);
static unsigned int trie_lookup_value(const struct trie_node *,
const ovs_be32 value[],
+ unsigned int value_bits,
unsigned int *checkbits);
static void trie_destroy(struct trie_node *);
static void trie_insert(struct cls_trie *, const struct cls_rule *, int mlen);
@@ -1828,7 +1829,7 @@ find_match_wc(const struct cls_subtable *subtable, const struct flow *flow,
mask = MINIFLOW_GET_BE32(&subtable->mask.masks, tp_src);
value = ((OVS_FORCE ovs_be32 *)flow)[TP_PORTS_OFS32] & mask;
- trie_lookup_value(subtable->ports_trie, &value, &mbits);
+ trie_lookup_value(subtable->ports_trie, &value, 32, &mbits);
((OVS_FORCE ovs_be32 *)&wc->masks)[TP_PORTS_OFS32] |=
mask & htonl(~0 << (32 - mbits));
@@ -2135,7 +2136,7 @@ trie_next_node(const struct trie_node *node, const ovs_be32 value[],
*/
static unsigned int
trie_lookup_value(const struct trie_node *node, const ovs_be32 value[],
- unsigned int *checkbits)
+ unsigned int n_bits, unsigned int *checkbits)
{
unsigned int ofs = 0, match_len = 0;
const struct trie_node *prev = NULL;
@@ -2154,8 +2155,13 @@ trie_lookup_value(const struct trie_node *node, const ovs_be32 value[],
if (node->n_rules > 0) {
match_len = ofs;
}
+ if (ofs >= n_bits) {
+ *checkbits = n_bits; /* Full prefix. */
+ return match_len;
+ }
}
- /* Dead end, exclude the other branch if it exists. */
+ /* node == NULL. Full match so far, but we came to a dead end.
+ * need to exclude the other branch if it exists. */
*checkbits = !prev || trie_is_leaf(prev) ? ofs : ofs + 1;
return match_len;
}
@@ -2172,7 +2178,7 @@ trie_lookup(const struct cls_trie *trie, const struct flow *flow,
if (mf_are_prereqs_ok(mf, flow)) {
return trie_lookup_value(trie->root,
&((ovs_be32 *)flow)[mf->flow_be32ofs],
- checkbits);
+ mf->n_bits, checkbits);
}
*checkbits = 0; /* Value not used in this case. */
return UINT_MAX;