summaryrefslogtreecommitdiff
path: root/src/ipcpd/unicast
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2026-05-25 14:54:35 +0200
committerSander Vrijders <sander@ouroboros.rocks>2026-05-27 15:55:08 +0200
commit347f6285d95c6c802a3efbab107c55d0b83036e3 (patch)
tree65bac60d07c148d89287bd23a5b48152e09ab826 /src/ipcpd/unicast
parentb2dc1d7ec76d86a640b70dea0e92a81e1990f019 (diff)
downloadouroboros-347f6285d95c6c802a3efbab107c55d0b83036e3.tar.gz
ouroboros-347f6285d95c6c802a3efbab107c55d0b83036e3.zip
ipcpd: Close dt stat_used race vs rib readdir
The stat_used function updated dt.stat[fd].stamp under the per-stat mutex, released it, then took dt.lock wrlock to bump dt.n_flows. A concurrent dt_rib_readdir holding dt.lock rdlock between those two critical sections saw the new stamp but the old n_flows. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/ipcpd/unicast')
-rw-r--r--src/ipcpd/unicast/dt.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/ipcpd/unicast/dt.c b/src/ipcpd/unicast/dt.c
index cc54efa1..8f5eb775 100644
--- a/src/ipcpd/unicast/dt.c
+++ b/src/ipcpd/unicast/dt.c
@@ -370,6 +370,12 @@ static struct rib_ops r_ops = {
};
#ifdef IPCP_FLOW_STATS
+/*
+ * Hold dt.lock + per-stat together: dt_rib_readdir samples n_flows
+ * under rdlock and walks stamps under per-stat; updates must be
+ * atomic w.r.t. that snapshot or the malloc(n_flows) buffer can
+ * overflow.
+ */
static void stat_used(int fd,
uint64_t addr)
{
@@ -377,6 +383,7 @@ static void stat_used(int fd,
clock_gettime(CLOCK_REALTIME_COARSE, &now);
+ pthread_rwlock_wrlock(&dt.lock);
pthread_mutex_lock(&dt.stat[fd].lock);
memset(&dt.stat[fd], 0, sizeof(dt.stat[fd]));
@@ -384,12 +391,9 @@ static void stat_used(int fd,
dt.stat[fd].stamp = (addr != INVALID_ADDR) ? now.tv_sec : 0;
dt.stat[fd].addr = addr;
- pthread_mutex_unlock(&dt.stat[fd].lock);
-
- pthread_rwlock_wrlock(&dt.lock);
-
(addr != INVALID_ADDR) ? ++dt.n_flows : --dt.n_flows;
+ pthread_mutex_unlock(&dt.stat[fd].lock);
pthread_rwlock_unlock(&dt.lock);
}
#endif