onas_ht_insert: fix issue causing active bckts to be unlinked from ht->head chain #1712
Merged
val-ms merged 1 commit intoCisco-Talos:mainfrom May 4, 2026
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes a bug in clamonacc’s inotify hash table where hash collisions could cause an already-active bucket to be re-linked into ht->head/ht->tail, breaking the activated-bucket linked list traversal (impacting OnAccessExcludePath processing).
Changes:
- Track whether a bucket was newly initialized during
onas_ht_insert. - Only append a bucket to the activated-bucket chain when it is newly created.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
When onas_ht_insert() adds an element whose hash maps to an existing bucket, the bucket is already part of the activated-bucket list. The old code appended that same bucket to the list again, resetting bckt->next to NULL and making any following buckets unreachable from ht->head. OnAccessExcludePath walks the activated-bucket list when removing watched paths. If a collision corrupts that list, some active directories can be skipped and remain watched. Track whether onas_ht_insert() allocated a new bucket, and only link the bucket into ht->head/ht->tail when it is new. Colliding elements are still inserted into the existing bucket without changing the bucket list.
5965948 to
5984287
Compare
val-ms
approved these changes
Apr 30, 2026
Contributor
val-ms
left a comment
There was a problem hiding this comment.
Re: the force push: I fixed super minor formatting issues to resolve our format checks, and added detail to the commit message.
Your change looks great. Thank you for solving this. I can that you put a lot of thought into it. I really appreciated the diagrams, they helped a lot with review.
Contributor
Author
|
@val-ms Thanks for the review! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Whenever there was a hash collision,
onas_ht_insertwould try to reinsert the pointer to a preexisting bckt into theht->headlist of buckets, even though that bucket would have already been put into the list when it was first initialized w/onas_bucket_init().This can cause a break in the ht->head chain where some active bckts can not be accessed via iterating via
bckt = ht->head+bckt = bckt->next, due to setting bckt->next to NULL.This causes issues when trying to process
OnAccessExcludePath, where iterating over the linked list of bckts currently causes some directories to not be excluded when they shouldHere's a simple diagram to illustrate how
onas_ht_insertis currently broken w/ hash collisions:Lets say we first insert two bckts w/
onas_ht_insert, let B1 be the first bckt, & B2 be the second bckt:let H:
ht->head, T:ht->tail-->: link/bckt->next,<--:bckt-prevfirst insertion:
second insertion:
Normally, the third insertion for B3 would seem pretty intuitive:
Now lets consider what happens if, for the third insertion, instead of a new bucket, B3, we try inserting B1 again:
Now we can no longer access bckt B2 via
bckt = ht->head&bckt = bckt->next, which, as mentioned, is what is used to iterate over each bucket forOnAccessExcludePath:clamav/clamonacc/inotif/inotif.c
Lines 534 to 554 in 9fe785d
Guard against this issue by only inserting the bckt if this is a newly initialized bckt