Hide the bundled OpenSSL's symbols from other libraries - #12
Merged
Merged
Conversation
openssl.so links OpenSSL statically but exported all of it, unversioned. A system libpq (the pg gem) then bound its OpenSSL 3 calls to Ruby's copy, and with pg loaded first openssl.so called into libssl.so.3 instead. On the OpenSSL 1.x series (1.8 through 3.1) that crashes Net::HTTPS or fails Postgres TLS handshakes in any app that uses both. Link with --exclude-libs for libssl.a and libcrypto.a. rbconfig keeps the flag, so native gems that link the bundled OpenSSL (puma) get it too, and the package tests now fail a build whose extensions export OpenSSL. Claude-Session: https://claude.ai/code/session_0146HthzF4yTdERCfixDX2Mh
This was referenced Sep 29, 2026
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.
openssl.solinks OpenSSL statically but exports all of it without symbol versions (about 1,800 symbols on 2.7.8). Two things go wrong when a system library that uses OpenSSL 3 is loaded in the same process, such as libpq through the pg gem, which every Rails app on Postgres loads:SSL_new,SSL_CTX_newand other OpenSSL 3 calls bind to Ruby's static copy (confirmed withLD_DEBUG=bindings).openssl.so's own calls go tolibssl.so.3, and Net::HTTPS segfaults inpeer_cert.On the OpenSSL 1.x series (1.8 through 3.1), this breaks pg together with HTTPS: segfaults,
munmap_chunk(): invalid pointer, and failed TLS handshakes to Postgres even withsslmode=disable. The 3.2+ series only work by luck, because both copies are OpenSSL 3.Changes
-Wl,--exclude-libs,libssl.a:libcrypto.a. It can't beALL, because libruby is static and itsrb_*symbols have to stay exported. rbconfig keeps the flag, so native gems that link the bundled OpenSSL (puma) also stop exporting it.check_openssl_hidden!fails a Linux build if any.soexportsSSL_neworCRYPTO_malloc. It flags the current 2.3.8-3 and 2.7.8-3 releases and passes the new builds.package.rbis part of the build fingerprint, so each version gets a new revision the next time it's released.Testing
I built arm64 packages locally with
bin/package-linuxand tested each inubuntu:24.04with the system's libpq (OpenSSL 3), a local Postgres, and HTTPS to rubygems.org. Every combination was tested: both load orders, withsslmode=requireandsslmode=disable.munmap_chunkin all 4peer_certsegfault, TLS error)2**64still correcthttps://claude.ai/code/session_0146HthzF4yTdERCfixDX2Mh