-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Fix MSAN use-after-free in Lua HeaderMapIterator destruction #43204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Hi @ashutosh321607, welcome and thank you for your contribution. We will try to review your Pull Request as quickly as possible. In the meantime, please take a look at the contribution guidelines if you have not done so already. |
Sorry, but I didn't get this. Ideally, if the HeaderMapWrapper still keep the the iterator, than the iterator should not be destroyed? |
| }); | ||
| } | ||
|
|
||
| HeaderMapIterator::~HeaderMapIterator() { parent_.onIteratorDestroyed(this); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When HeaderMapIterator is destroyed, the reference number of this object should be zero, then the parent_ should not hold this object in its iterator_ field?
Or in other word, if this object is destroyed, that means there no any LuaRef or LuaDeathRef keep this object, then should no one will call its markDead method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change is dangerous because the parent_ may be dangling reference if the parent HeaderMapWrapper object is destroyed first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the HeaderMapWrapper (parent) were destroyed before the HeaderMapIterator (child), the parent_ reference would become dangling, leading to undefined behavior when the iterator is eventually garbage collected.
To address this, I’ve refactored the implementation more a bit,
- HeaderMapIterator now holds a HeaderMapWrapper* parent_ pointer instead of a reference.
- I implemented onMarkDead() in HeaderMapIterator. When the parent releases the iterator (e.g., when the parent is destroyed), markDead() is called on the iterator. My override now sets parent_ = nullptr, effectively detaching the iterator.
- In the HeaderMapIterator destructor, I now check if (parent_ != nullptr) before notifying the parent.
wbpcode
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution.
|
/wait-any |
This change fixes a memory safety issue detected by MSAN where HeaderMapWrapper could hold a dangling reference to a HeaderMapIterator that was being garbage collected by Lua, or attempt to call markDead() on a partially destroyed iterator. When HeaderMapIterator is destroyed by the Lua GC, it now explicitly notifies its parent HeaderMapWrapper. The wrapper then releases its reference to the iterator using a new resetWithoutMarkDead() method. This method avoids calling markDead() on the iterator, which is critical because invoking methods on an object currently executing its destructor is unsafe and triggers MSAN errors. This ensures the HeaderMapWrapper's reference is cleanly nullified without accessing the dying object. Signed-off-by: Ashutosh Garg <[email protected]>
Basically
The fix ensures that when the |
|
I think then the correct fix should be do cleanup (all every one's markDead) before call the Sorry for the nagging. I want to ensure we are in the correct direction. Ideally, we should add destructor to object the inherit from LuaBaseObject but use the markDead to manage the lifetime. |
Commit Message: Fix MSAN use-after-free in Lua HeaderMapIterator destruction
Additional Description: This change fixes a memory safety issue detected by MSAN where HeaderMapWrapper could hold a dangling reference to a HeaderMapIterator that was being garbage collected by Lua, or attempt to call markDead() on a partially destroyed iterator.
When HeaderMapIterator is destroyed by the Lua GC, it now explicitly notifies its parent HeaderMapWrapper. The wrapper then releases its reference to the iterator using a new resetWithoutMarkDead() method. This method avoids calling markDead() on the iterator, which is critical because invoking methods on an object currently executing its destructor is unsafe and triggers MSAN errors.
This ensures the HeaderMapWrapper's reference is cleanly nullified without accessing the dying object.
Risk Level: Low
Testing: Check with existing tests, none of the existing test failing
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]