lltable: Fix use-after-free race in llentry_free()#2219
Open
TeddyEngel wants to merge 1 commit into
Open
Conversation
When callout_stop() returns 0, the timer callback is currently executing on another CPU. The original code proceeded to free the llentry anyway, causing a use-after-free when the timer callback (e.g., arptimer) accessed the freed memory. Fix by checking the callout_stop() return value: - If >0: timer was pending and successfully cancelled, drop timer's ref - If 0 and refcnt>1: another thread racing with timer, drop ref and bail; timer's llentry_free() will free the entry - If 0 and refcnt==1: we ARE the timer, proceed to free - If <0: timer was not scheduled, proceed normally PR: 285813 Signed-off-by: Teddy Engel <engel.teddy@gmail.com>
39b5f4f to
6013202
Compare
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.
Fix a use-after-free race condition in
llentry_free()that causes kernel panics when ARP timer callbacks race with interface destruction.Problem
When
callout_stop()returns 0, the timer callback (e.g.,arptimer()) is currently executing on another CPU. The original code proceeded to free thellentryanyway viaLLE_FREE_LOCKED(), causing use-after-free when the timer callback subsequently accessed the freed memory.The race window:
llentry_free()callout_stop(&lle->lle_timer)returns 0 (timer is executing)LLE_FREE_LOCKED(lle)- destroys lock, frees entryarptimer()on another CPU tries to access the freed entryCrash Signatures
This race manifests as various panics depending on timing:
Crash at lock acquisition (
rw_lock = 0x6 = RW_DESTROYED):Crash at NULL dereference:
Zeroed callout wheel entry:
cc->cc_callwheel[]entry entirely zeroed outSolution
Check
callout_stop()return value and handle each case:> 0: Timer was pending and successfully cancelled. Drop timer's reference, proceed to free.== 0: Timer is currently executing. Userefcntto distinguish:refcnt > 1: Another thread is racing with the timer. The entry is already unlinked (KASSERT), so the timer will skip itsLLE_REMREF. Drop one ref and bail; timer'sllentry_free()call will free the entry.refcnt == 1: We are the timer callback and already dropped our ref. Proceed to free.< 0: Timer was not scheduled. Proceed normally.Problem Report