Skip to content

Fix mysqlnd pipe crash #13782

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

Closed
wants to merge 6 commits into from
Closed

Conversation

nielsdos
Copy link
Member

@nielsdos nielsdos commented Mar 21, 2024

The individual commits have descriptions that explain the change. This fixes the bug fully on the master branch.
I tested this with both persistent and non-persistent connections. As mysqlnd's stream handling is a bit tricky and has some hacks, it's best to review this with at least 2 people.

As for backporting: All commits except the first one can be backported to stable branches I think, which means that in that case it's fixed on stable branches that use NTS. On ZTS, I'm not entirely sure if there's still cases where it will crash. Since the resources are removed from the persistent list, and managed by the extension itself now, it may work around the crash that the old code was protecting against.

Should fix GH-10599.

To test with ASAN on Windows (to reproduce the crash), you need to modify configure.js:
Find ADD_FLAG('CFLAGS', ' /wd4996 '); and change it into ADD_FLAG('CFLAGS', ' /wd4996 /fsanitize=address ');.

What happens is that the persistent network stream resource gets freed, yet
stays inside EG(persistent_list). This causes a crash on shutdown when the
persistent list is getting cleared, as the engine will try to free the network
stream again.

The code in close_stream gets confused between persistent vs
non-persistent allocations when EG(active) is false.
This code was introduced in c3019a1 to fix crashes when the persistent list
gets destroyed before module shutdown is called. This is indeed a potential
problem that was fixed on the master branch in 5941cda.

This fixes the crash reason of phpGH-10599.
This fixes the memory leak part of phpGH-10599.
This prevents the code from getting desynced again, which was the reason
for the leak of phpGH-10599.
…i connection

The code originally posted in phpGH-10599 triggers the bug for
non-persistent connections, but changing the host to `p:.` reveals that
there is also a crash bug for persistent connections.
@nielsdos nielsdos force-pushed the fix-mysqlnd-pipe-crash branch from c8fb571 to b30796f Compare March 22, 2024 12:15
@nielsdos nielsdos requested a review from kamil-tekiela March 22, 2024 12:57
@nielsdos nielsdos marked this pull request as ready for review March 22, 2024 12:57
@nielsdos nielsdos requested a review from SakiTakamachi as a code owner March 22, 2024 12:57
Copy link
Member

@SakiTakamachi SakiTakamachi left a comment

Choose a reason for hiding this comment

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

I've looked over the code three times and it looks good to me.

I'll wait for @kamil-tekiela 's review.

@kamil-tekiela
Copy link
Member

I recuse myself from reviewing this because I have no idea what's going on here. But I have no objections to this. If you believe this is the right fix, go ahead and merge it. Maybe some other senior developer can take a quick look at it too if you want someone else's review.

@nielsdos
Copy link
Member Author

nielsdos commented Apr 8, 2024

Okay, thanks for trying to check anyway, I'll ask somebody for another review.

@nielsdos nielsdos requested a review from iluuu1994 April 8, 2024 17:51
@bukka
Copy link
Member

bukka commented Apr 10, 2024

This is very ugly. I don't mean your particular change but already the existing way of doing this. I will try to think if we could come up with something cleaner (at least for master). Need to get a bit better understanding of the whole problem first.

@iluuu1994
Copy link
Member

I'll leave the review up to Jakub then. @bukka Ping me if you don't want to look at this after all.

Copy link
Member

@bukka bukka left a comment

Choose a reason for hiding this comment

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

So I looked properly into this and think this is fine as a fix. It's just extending the current hacky way how to make stream not to register (meaning delete them immediately after registration) the resource...

I have been thinking about a proper solution and I think this should be addressed in the stream layer by introuction of the new stream open option. This is however not such a small task because creation of the stream is handled by each wrapper independently (in stream_opener) so it will require updating wrappers (we probably just need it in plain, xp and ssl for now) and introducing various new extended functions that will propagate this option all the way to _php_stream_alloc which can skip the resource registration. Created stream should be then aware so there won't be a need to use further hacks like passing PHP_STREAM_FREE_RSRC_DTOR which is completely misused here (it is just used to skip removing item from the list but that is originally there because we wont to do the removal in shutdown but that won't happen here because it's not in the list - so hacky... :) ). This is something that can happen in master only though.

@nielsdos
Copy link
Member Author

I have been thinking about a proper solution and I think this should be addressed in the stream layer by introuction of the new stream open option.

Yeah, I had also tried looking into this but quickly gave up on this 😅
Anyway, thanks for the review. I'll merge this into master, and if no issues surface after a while, I'm going to backport the safe & backportable part of this to lower branch.

@nielsdos nielsdos closed this in dd1a32d Apr 21, 2024
nielsdos added a commit to nielsdos/php-src that referenced this pull request May 25, 2024
This partially backports that PR to stable branches as it has been in master
without reported problems so far.
It's only a partial backport because the stable branches don't have the
ZTS persistent resource fix that would fix shutdown crashes, i.e. the
code change in mysqlnd_vio's close_stream is not backported.
nielsdos added a commit to nielsdos/php-src that referenced this pull request May 25, 2024
This partially backports that PR to stable branches as it has been in master
without reported problems so far.
It's only a partial backport because the stable branches don't have the
ZTS persistent resource fix that would fix shutdown crashes, i.e. the
code change in mysqlnd_vio's close_stream is not backported.

Closes phpGH-10599.
nielsdos added a commit that referenced this pull request May 30, 2024
This partially backports that PR to stable branches as it has been in master
without reported problems so far.
It's only a partial backport because the stable branches don't have the
ZTS persistent resource fix that would fix shutdown crashes, i.e. the
code change in mysqlnd_vio's close_stream is not backported.

This is fully fixed on master.

Closes GH-14324.
Closes GH-10599.
nielsdos added a commit that referenced this pull request May 30, 2024
* PHP-8.2:
  Partially backport GH-13782 to stable branches
nielsdos added a commit that referenced this pull request May 30, 2024
* PHP-8.3:
  Partially backport GH-13782 to stable branches
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants