diff options
| author | Dimitri Staessens <dimitri@ouroboros.rocks> | 2026-06-01 08:37:39 +0200 |
|---|---|---|
| committer | Sander Vrijders <sander@ouroboros.rocks> | 2026-06-03 08:02:34 +0200 |
| commit | b88c120f68b0e9f779fa0071a2ad095b93d5aaf6 (patch) | |
| tree | 585dbe967e1d8a84a2b6aa4460b3d6e3f8ce86f1 | |
| parent | 89426f0e796f1ad0141d81987dfa3bf98a4a7ede (diff) | |
| download | ouroboros-b88c120f68b0e9f779fa0071a2ad095b93d5aaf6.tar.gz ouroboros-b88c120f68b0e9f779fa0071a2ad095b93d5aaf6.zip | |
lib: Fix overflow in ssm_flow_set_notify
ssm_flow_set_notify wrote past the fqueue because of a missing bound
check, corrupting adjacent memory under burst. Drop redundant FLOW_PKT
when full and reserve the last slot for control events so they aren't
starved by data-plane traffic.
Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
| -rw-r--r-- | src/lib/ssm/flow_set.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/src/lib/ssm/flow_set.c b/src/lib/ssm/flow_set.c index cb38e6fd..2e33b408 100644 --- a/src/lib/ssm/flow_set.c +++ b/src/lib/ssm/flow_set.c @@ -299,26 +299,34 @@ void ssm_flow_set_notify(struct ssm_flow_set * set, int event) { struct flowevent * e; + ssize_t idx; assert(set); assert(!(flow_id < 0) && flow_id < SYS_MAX_FLOWS); pthread_mutex_lock(set->lock); - if (set->mtable[flow_id] == -1) { + idx = set->mtable[flow_id]; + if (idx == -1) { pthread_mutex_unlock(set->lock); return; } - e = fqueue_ptr(set, set->mtable[flow_id]) + - set->heads[set->mtable[flow_id]]; + /* Ring full: drop redundant FLOW_PKT, reserve a slot for ctrl. */ + if (set->heads[idx] >= SSM_RBUFF_SIZE + || (event == FLOW_PKT && set->heads[idx] >= SSM_RBUFF_SIZE - 1)) { + pthread_mutex_unlock(set->lock); + return; + } + + e = fqueue_ptr(set, idx) + set->heads[idx]; e->flow_id = flow_id; e->event = event; - ++set->heads[set->mtable[flow_id]]; + ++set->heads[idx]; - pthread_cond_signal(&set->conds[set->mtable[flow_id]]); + pthread_cond_signal(&set->conds[idx]); pthread_mutex_unlock(set->lock); } |
