fix: make kstorage write_kstorage find+replace atomic - #293
Open
AYwlilwYA wants to merge 1 commit into
Open
Conversation
write_kstorage() looked up the existing node under rcu_read_lock() but replaced it under the group spinlock. Two writers racing on the same did could both find the same old node; the second hlist_replace_rcu() on an already-replaced node wrote through its poisoned ->pprev (LIST_POISON2), causing a kernel Oops (observed in apd during APatch re-authorization after a system_server soft restart). Move the lookup inside the spinlock so find+replace/add are atomic.
Collaborator
|
kstorage在什么情况下会导致这样的情况,自旋锁会导致大量写入被拦截排队。正常使用不会触发到 |
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.
Problem
write_kstorage()had a race between finding an existing entry and replacingit:
Two writers racing on the same
didcould both find the sameoldnode.The first thread replaces it (
old->pprevbecomesLIST_POISON2); the secondthread then calls
hlist_replace_rcu()on the already-replaced node andWRITE_ONCE(*old->pprev, new)writes through the poisoned pointer(
dead000000000122), causing a kernel Oops.Observed in the field: apd (APatch daemon) crashed with
Unable to handle kernel paging request at virtual address dead000000000122(LIST_POISON2) during APatch re-authorization after a system_server soft
restart, exactly at
hlist_replace_rcu()'sold->pprev = LIST_POISON2.Fix
Move the lookup inside the group spinlock so find + replace/add are atomic
under the same lock.
remove_kstorage()already does its find+del under thelock and is unaffected.
Verified:
kstorage.ccompiles cleanly (aarch64, no new warnings).