In rte_hash_iterate, the reader lock did not protect the
while loop which checks empty entry. This created a race
condition that the entry may become empty when enters
the lock, then a wrong key data value would be read out.
This commit extends the protected region.
Fixes: f2e3001b53ec ("hash: support read/write concurrency")
Cc: [email protected]
Signed-off-by: Yipeng Wang <[email protected]>
Reported-by: Honnappa Nagarahalli <[email protected]>
---
lib/librte_hash/rte_cuckoo_hash.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lib/librte_hash/rte_cuckoo_hash.c
b/lib/librte_hash/rte_cuckoo_hash.c
index f7b86c8..eba13e9 100644
--- a/lib/librte_hash/rte_cuckoo_hash.c
+++ b/lib/librte_hash/rte_cuckoo_hash.c
@@ -1317,16 +1317,19 @@ rte_hash_iterate(const struct rte_hash *h, const void
**key, void **data, uint32
bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES;
idx = *next % RTE_HASH_BUCKET_ENTRIES;
+ __hash_rw_reader_lock(h);
/* If current position is empty, go to the next one */
while (h->buckets[bucket_idx].key_idx[idx] == EMPTY_SLOT) {
(*next)++;
/* End of table */
- if (*next == total_entries)
+ if (*next == total_entries) {
+ __hash_rw_reader_unlock(h);
return -ENOENT;
+ }
bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES;
idx = *next % RTE_HASH_BUCKET_ENTRIES;
}
- __hash_rw_reader_lock(h);
+
/* Get position of entry in key table */
position = h->buckets[bucket_idx].key_idx[idx];
next_key = (struct rte_hash_key *) ((char *)h->key_store +
--
2.7.4