Skip to content

fix: hold the rate limit lock across the address lookup - WPB-15070 - #77

Open
bsinou wants to merge 1 commit into
devfrom
WPB-15070-ratelimit-lock-dev
Open

bsinou wants to merge 1 commit into
devfrom
WPB-15070-ratelimit-lock-dev

Conversation

@bsinou

@bsinou bsinou commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator

Port of #29 to dev, rewritten.

Issue

In ratelimit_is_address_limited, ur_addr_map_get runs without rate_limit_main_mutex, concurrently with inserts from other threads and with the pruning, which frees entries (addr_list_foreach_del_condition). A thread can read the map while it changes, or use an entry that was just freed.

Change

Take rate_limit_main_mutex before the lookup and hold it until the entry is no longer used: on the existing-entry paths it is released after the entry mutex, and the new-entry path reuses it for the insert instead of locking again. Lock order is main, then entry, then allowlist, and nothing takes them in another order.

#29 could not be ported as is: it unlocked right after the lookup (the entry could still be freed), unlocked a second time on the rate-limited path, and never unlocked when the address was new, which deadlocks on the first 401 from a new IP.

Testing

Built on Ubuntu 24.04 as in CI: make check passes, and the TCP, TLS, UDP and DTLS client tests pass.

The "rate limit by IP" client test reports FAIL on dev as well, without failing the job: it relies on the default limit of 1000 401 responses per window, which the test never reaches, and exit $? after echo FAIL exits 0. I ran the server by hand with --401-req-limit=3 instead: valid credentials are served, the address is rate limited after 3 responses, and the server stays responsive, the same as on dev.

@bsinou
bsinou requested a review from a team as a code owner November 11, 2026 08:27

@z-dule z-dule left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it would work, but having nested labels inside an else is terrible practice!

ur_addr_map_get ran without rate_limit_main_mutex, concurrently with
inserts and with the pruning that frees entries. Hold the lock from the
lookup until the entry is no longer used, new entries included.

Port of #29, which unlocked twice on one path and not at all on another.
@bsinou
bsinou force-pushed the WPB-15070-ratelimit-lock-dev branch from 751db75 to 179a8e3 Compare November 11, 2026 12:11

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants