-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix #5355: Add null pointer check in RequestEnd() to prevent use-after-free crash #5356
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: v3.0
Are you sure you want to change the base?
Conversation
…r-free crash This commit addresses a use-after-free race condition that could cause ProxySQL to crash with SIGSEGV during COM_CHANGE_USER timeout scenarios. Root Cause: ----------- When a session is in RESETTING_CONNECTION status and the backend times out during COM_CHANGE_USER, the code calls RequestEnd() to handle the error. However, RequestEnd() accesses client_myds without null checks. If the session is marked as unhealthy and deleted by ProcessAllSessions_Healthy0() while RequestEnd() is still executing, this results in a use-after-free crash. The crash is particularly likely during AWS Aurora failures when: 1. Monitor detects Aurora master timeouts 2. Multiple sessions experience connection issues 3. Many client connections are marked unhealthy 4. The high volume of session deletions increases race condition probability Fix: ---- Added a null pointer check before accessing client_myds in the unexp_com_pings handling code within RequestEnd(). This is a defensive programming fix that prevents the crash when client_myds has been freed. A more robust fix would involve proper session lifecycle management with reference counting. Fixes: #5355
Summary of ChangesHello @renecannao, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly improves the stability of ProxySQL by resolving a critical use-after-free vulnerability. The change prevents crashes that could occur when handling Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
📝 WalkthroughWalkthroughA null pointer guard was added in Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 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.
Code Review
This pull request aims to fix a use-after-free crash by adding a null pointer check for client_myds. While the intention is correct, the current implementation is not sufficient to fully prevent the race condition described. The client_myds pointer can become invalid at any point during the execution of the if block, not just at the entry. I've added a comment explaining why the fix is incomplete and suggesting a more robust approach.
| if (client_myds->unexp_com_pings) { | ||
| // Fix #5355: Add null pointer check for client_myds to prevent use-after-free crash | ||
| // when session is deleted while RequestEnd() is still executing (e.g., during COM_CHANGE_USER timeout) | ||
| if (client_myds && client_myds->unexp_com_pings) { |
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.
While adding a null check for client_myds is a good defensive measure, this fix is incomplete. The race condition described can invalidate client_myds at any point. After this check, client_myds is dereferenced multiple times inside the block (lines 8889, 8891, 8892, etc.) without further checks. If client_myds becomes null or a dangling pointer after this initial check, the program will still crash.
A truly safe fix would require a synchronization mechanism like a lock to protect access to the session and its members throughout this operation. Given the constraints, a more robust change would be to re-validate the client_myds pointer before each dereference inside this block.
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.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/MySQL_Session.cpp (1)
8886-8892:⚠️ Potential issue | 🟠 MajorAdd proper synchronization to prevent use-after-free; null check alone is insufficient.
The null guard at line 8889 prevents NULL dereference but not UAF:
client_mydscan be freed and remain non-NULL between the check and the multiple subsequent dereferences (lines 8890–8912). Additionally, the destructor does not null the pointer afterdelete client_myds(line 798), leaving a dangling pointer. Implement either (a) mutual exclusion preventing session deletion during RequestEnd, or (b) reference counting or lifetime tracking to serialize or safely defer deletion until RequestEnd completes.



Summary
This PR fixes a use-after-free race condition that causes ProxySQL to crash with SIGSEGV during COM_CHANGE_USER timeout scenarios.
Issue
Fixes #5355
Root Cause
When a session is in
RESETTING_CONNECTIONstatus and the backend times out duringCOM_CHANGE_USER, the code callsRequestEnd()to handle the error. However,RequestEnd()accessesclient_mydswithout null checks.If the session is marked as unhealthy and deleted by
ProcessAllSessions_Healthy0()whileRequestEnd()is still executing, this results in a use-after-free crash at:The crash is particularly likely during AWS Aurora failures when:
Fix
Added a null pointer check before accessing
client_mydsin theunexp_com_pingshandling code withinRequestEnd():This is a defensive programming fix that prevents the crash when
client_mydshas been freed.Test plan
Related
See issue #5355 for detailed root cause analysis and alternative solution approaches.
Summary by CodeRabbit