Skip to content

ext/openssl: Free prior SSL_SESSION on Openssl\Session::__unserialize#22040

Closed
iliaal wants to merge 1 commit into
php:masterfrom
iliaal:fix/openssl-ss005-session-unserialize-leak
Closed

ext/openssl: Free prior SSL_SESSION on Openssl\Session::__unserialize#22040
iliaal wants to merge 1 commit into
php:masterfrom
iliaal:fix/openssl-ss005-session-unserialize-leak

Conversation

@iliaal

@iliaal iliaal commented May 13, 2026

Copy link
Copy Markdown
Contributor

Openssl\Session::__unserialize() overwrote obj->session without freeing the previous SSL_SESSION when called a second time on the same instance, leaking an SSL_SESSION. These live in OpenSSL's allocator and bypass memory_limit, so a long-running worker that hits the repeat path accumulates an unbounded leak. There's no legitimate reason to re-run __unserialize() on a live instance, so it now throws when obj->session is already populated, before any overwrite.

@ndossche ndossche left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder if calling __unserialize directly like this shouldn't simply be blocked.
Could have a check at start for obj->session != NULL and then throw if it isn't NULL. I wonder if there's a legitimate use-case for calling __unserialize directly. I'd rather just shut down a footgun.

Calling __unserialize() on an Openssl\Session that already holds an
SSL_SESSION overwrote obj->session without freeing the prior one, leaking
an SSL_SESSION (OpenSSL's allocator, bypasses memory_limit). There is no
legitimate use for re-running __unserialize() on a live instance, so
reject it: throw when obj->session is already populated, before any
overwrite.

Closes phpGH-22040
@iliaal iliaal force-pushed the fix/openssl-ss005-session-unserialize-leak branch from 7220e28 to 5ebc4a9 Compare June 15, 2026 21:41
@iliaal

iliaal commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Agreed, better to shut the footgun. Throwing on obj->session != NULL at the top of __unserialize() skips the overwrite entirely, so there's no SSL_SESSION leak, and since it no longer reaches the second $id write it also avoids the zend_update_property_string engine-bug leak. Switched to that and updated the test to expect the new throw, which drops the #22039 dependency.

@iliaal iliaal requested a review from ndossche June 16, 2026 01:43
@iliaal iliaal closed this in 943720b Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants