Coverity reports a data race where coverage_read() accesses idx_count
without holding the coverage_mutex, while coverage_run() writes to
idx_count with the mutex held (as is done 1 out of 1 times when
writing).

The race occurs when coverage_read() reads idx_count to calculate the
array index into c[i]->min[] without synchronization. If coverage_run()
concurrently updates idx_count, coverage_read() could:

1. Read a stale value of idx_count with no memory barrier guaranteeing
   visibility of the update
2. Access the wrong index in the min[] array, reporting statistics from
   the wrong time slot

Fix by capturing idx_count once while holding the mutex, then using
that consistent snapshot value when accessing the arrays.

Fixes: 98cf638b19c2 ("coverage: Reimplement the "ovs-appctl coverage/show" 
command.")
Acked-by: Mike Pattrick <[email protected]>
Signed-off-by: Eelco Chaudron <[email protected]>
---
 lib/coverage.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/coverage.c b/lib/coverage.c
index a95b6aa25..24792fb77 100644
--- a/lib/coverage.c
+++ b/lib/coverage.c
@@ -223,6 +223,7 @@ coverage_read(struct svec *lines)
 {
     struct coverage_counter **c = coverage_counters;
     unsigned long long int *totals;
+    unsigned int last_idx;
     size_t n_never_hit;
     uint32_t hash;
     size_t i;
@@ -238,6 +239,7 @@ coverage_read(struct svec *lines)
 
     totals = xmalloc(n_coverage_counters * sizeof *totals);
     ovs_mutex_lock(&coverage_mutex);
+    last_idx = (idx_count - 1) % MIN_AVG_LEN;
     for (i = 0; i < n_coverage_counters; i++) {
         totals[i] = c[i]->total;
     }
@@ -252,8 +254,7 @@ coverage_read(struct svec *lines)
                 xasprintf("%-24s %5.1f/sec %9.3f/sec "
                           "%13.4f/sec   total: %llu",
                           c[i]->name,
-                          (c[i]->min[(idx_count - 1) % MIN_AVG_LEN]
-                           * 1000.0 / COVERAGE_RUN_INTERVAL),
+                          c[i]->min[last_idx] * 1000.0 / COVERAGE_RUN_INTERVAL,
                           coverage_array_sum(c[i]->min, MIN_AVG_LEN) / 60.0,
                           coverage_array_sum(c[i]->hr,  HR_AVG_LEN) / 3600.0,
                           totals[i]));
-- 
2.52.0

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to