Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 36 additions & 4 deletions libexec/package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,25 @@ def apply_source_patches(source)
# is declared inline without static, which C99 inline semantics (the default since
# GCC 5) turn into an undefined reference at link time.
inreplace(File.join(source, "lex.c"), "struct kwtable *\nrb_reserved_word", "static struct kwtable *\nrb_reserved_word")
when "init_only_exports"
# Old openssl extensions define stand-ins for functions their OpenSSL lacks
# (X509_STORE_set_ex_data, SSL_SESSION_cmp, ...), and 1.8's digest/sha2 has its own
# SHA256_Transform, all exported. When a system libcrypto.so.3 is already loaded
# (pg gem required first), calls to them bind to OpenSSL 3's functions, which crash
# on the old structs. Nothing links against these extensions, so they export only
# their Init function. The flag stays in their Makefiles, not rbconfig.
%w[openssl digest/md5 digest/sha1 digest/sha2 digest/rmd160].each do |name|
ext = File.join(source, "ext", name)
next unless File.exist?(File.join(ext, "extconf.rb"))

File.write(File.join(ext, "exports.map"), "{\n global: Init_*;\n local: *;\n};\n")
extconf = File.join(ext, "extconf.rb")
content = File.read(extconf)
raise PackageError, "#{extconf}: create_makefile not found" unless content.match?(/^\s*create_makefile\(/)
File.write(extconf, content.sub(/^(\s*)create_makefile\(/) do
"#{$1}$DLDFLAGS << \" -Wl,--version-script=\#{File.expand_path(\"exports.map\", $srcdir)}\"\n#{$1}create_makefile("
end)
end
else
raise PackageError, "unknown source patch: #{name}"
end
Expand Down Expand Up @@ -1063,12 +1082,25 @@ def check_abi!(root)
end
end

# See ruby_build_env: an exported OpenSSL symbol lets a system libpq bind to it.
# An exported symbol that the system OpenSSL also defines gets bound to it (or it to
# them) when both are loaded: see ruby_build_env and the init_only_exports patch. The
# bundled OpenSSL must be hidden everywhere, and the extensions that wrap or stand in
# for it may export nothing but their Init function.
def check_openssl_hidden!(root)
exporters = Dir.glob(File.join(root, "**", "*.so")).select do |path|
capture("nm", "-D", "--defined-only", path, allow_failure: true).match?(/ (SSL_new|CRYPTO_malloc)$/)
offenders = Dir.glob(File.join(root, "**", "*.so")).filter_map do |path|
symbols = capture("nm", "-D", "--defined-only", path, allow_failure: true).lines.map { |line| line.split.last }
symbols = if init_only_exports? && path.match?(%r{/(openssl|digest/(md5|sha1|sha2|rmd160))\.so\z})
symbols.grep_v(/\A(Init_\w+|_init|_fini|_edata|_end|__bss_start)\z/)
else
symbols.grep(/\A(SSL_new|CRYPTO_malloc)\z/)
end
"#{path}: #{symbols.first(5).join(", ")}" if symbols.any?
end
raise PackageError, "OpenSSL symbols exported by:\n #{exporters.join("\n ")}" unless exporters.empty?
raise PackageError, "OpenSSL symbols exported by:\n #{offenders.join("\n ")}" unless offenders.empty?
end

def init_only_exports?
Array(@series["patches"]).include?("init_only_exports")
end

def package!
Expand Down
92 changes: 92 additions & 0 deletions recipes/rubies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,110 @@ rubies:
series: '2.6'
url: https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.10.tar.bz2
sha256: 399e1f13e7fedc3c6ae2ff541bbf26c44dfb63b07b6c186fdd15b4e526e27e9c
2.7.0:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.gz
sha256: 8c99aa93b5e2f1bc8437d1bbbefd27b13e7694025331f77245d0c068ef1f8cbe
2.7.1:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.1.tar.gz
sha256: d418483bdd0000576c1370571121a6eb24582116db0b7bb2005e90e250eae418
2.7.2:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.gz
sha256: 6e5706d0d4ee4e1e2f883db9d768586b4d06567debea353c796ec45e8321c3d4
2.7.3:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.3.tar.gz
sha256: 8925a95e31d8f2c81749025a52a544ea1d05dad18794e6828709268b92e55338
2.7.4:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.4.tar.gz
sha256: 3043099089608859fc8cce7f9fdccaa1f53a462457e3838ec3b25a7d609fbc5b
2.7.5:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.5.tar.gz
sha256: 2755b900a21235b443bb16dadd9032f784d4a88f143d852bc5d154f22b8781f1
2.7.6:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.6.tar.gz
sha256: e7203b0cc09442ed2c08936d483f8ac140ec1c72e37bb5c401646b7866cb5d10
2.7.7:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.7.tar.gz
sha256: e10127db691d7ff36402cfe88f418c8d025a3f1eea92044b162dd72f0b8c7b90
2.7.8:
series: '2.7'
url: https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.8.tar.gz
sha256: c2dab63cbc8f2a05526108ad419efa63a67ed4074dbbcf9fc2b1ca664cb45ba0
3.0.0:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz
sha256: a13ed141a1c18eb967aac1e33f4d6ad5f21be1ac543c344e0d6feeee54af8e28
3.0.1:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.1.tar.gz
sha256: 369825db2199f6aeef16b408df6a04ebaddb664fb9af0ec8c686b0ce7ab77727
3.0.2:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.2.tar.gz
sha256: 5085dee0ad9f06996a8acec7ebea4a8735e6fac22f22e2d98c3f2bc3bef7e6f1
3.0.3:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.3.tar.gz
sha256: 3586861cb2df56970287f0fd83f274bd92058872d830d15570b36def7f1a92ac
3.0.4:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.4.tar.gz
sha256: 70b47c207af04bce9acea262308fb42893d3e244f39a4abc586920a1c723722b
3.0.5:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.5.tar.gz
sha256: 9afc6380a027a4fe1ae1a3e2eccb6b497b9c5ac0631c12ca56f9b7beb4848776
3.0.6:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.6.tar.gz
sha256: 6e6cbd490030d7910c0ff20edefab4294dfcd1046f0f8f47f78b597987ac683e
3.0.7:
series: '3.0'
url: https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.7.tar.gz
sha256: 2a3411977f2850431136b0fab8ad53af09fb74df2ee2f4fb7f11b378fe034388
3.1.0:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.0.tar.gz
sha256: 50a0504c6edcb4d61ce6b8cfdbddaa95707195fab0ecd7b5e92654b2a9412854
3.1.1:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.1.tar.gz
sha256: fe6e4782de97443978ddba8ba4be38d222aa24dc3e3f02a6a8e7701c0eeb619d
3.1.2:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.2.tar.gz
sha256: 61843112389f02b735428b53bb64cf988ad9fb81858b8248e22e57336f24a83e
3.1.3:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.3.tar.gz
sha256: 5ea498a35f4cd15875200a52dde42b6eb179e1264e17d78732c3a57cd1c6ab9e
3.1.4:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.4.tar.gz
sha256: a3d55879a0dfab1d7141fdf10d22a07dbf8e5cdc4415da1bde06127d5cc3c7b6
3.1.5:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.5.tar.gz
sha256: 3685c51eeee1352c31ea039706d71976f53d00ab6d77312de6aa1abaf5cda2c5
3.1.6:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.6.tar.gz
sha256: 0d0dafb859e76763432571a3109d1537d976266be3083445651dc68deed25c22
3.1.7:
series: '3.1'
url: https://cache.ruby-lang.org/pub/ruby/3.1/ruby-3.1.7.tar.gz
sha256: 0556acd69f141ddace03fa5dd8d76e7ea0d8f5232edf012429579bcdaab30e7b
3.2.0:
series: '3.2'
url: https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.0.tar.gz
sha256: daaa78e1360b2783f98deeceb677ad900f3a36c0ffa6e2b6b19090be77abc272
3.2.1:
series: '3.2'
url: https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.1.tar.xz
Expand Down
17 changes: 15 additions & 2 deletions recipes/series.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ series:
# because their openssl extensions predate OpenSSL 3; -fno-strict-overflow because
# their fixnum overflow checks rely on signed overflow wrapping, which GCC exploits from
# -O2 up (a 1.8.7 built without it evaluates 2**64 to 0); readline through a bundled
# libedit; no bundled msgpack/bootsnap; a version-appropriate native gem as the test.
# libedit; no bundled msgpack/bootsnap; a version-appropriate native gem as the test;
# init_only_exports so their openssl and digest extensions can't collide with a system
# OpenSSL 3 that the pg gem loads into the same process.
"1.8":
openssl: openssl1.0
baseruby: none
Expand All @@ -45,7 +47,7 @@ series:
install_doc: false
install_target: install-nodoc # 1.8 has no --disable-install-doc
cflags: "-O3 -fno-strict-overflow"
patches: [lex_c99]
patches: [lex_c99, init_only_exports]
freshen_config_guess: true
extra_out_ext: [tk, tcltklib, gdbm, dbm] # removed from the tree: 1.8 has no --with-out-ext
rubygems: rubygems1.8
Expand All @@ -56,6 +58,7 @@ series:
test_native_gem: { name: json, version: 1.8.6 }
"1.9":
openssl: openssl1.0
patches: [init_only_exports]
baseruby: none
use_libedit: true
install_doc: false
Expand All @@ -70,6 +73,7 @@ series:
test_native_gem: { name: json, version: 1.8.6 }
"2.0":
openssl: openssl1.0
patches: [init_only_exports]
baseruby: none
use_libedit: true
install_doc: false
Expand All @@ -83,6 +87,7 @@ series:
test_native_gem: { name: json, version: 1.8.6 }
"2.1":
openssl: openssl1.0
patches: [init_only_exports]
baseruby: none
use_libedit: true
install_doc: false
Expand All @@ -95,6 +100,7 @@ series:
test_native_gem: { name: json, version: 1.8.6 }
"2.2":
openssl: openssl1.0
patches: [init_only_exports]
baseruby: none
use_libedit: true
install_doc: false
Expand All @@ -107,6 +113,7 @@ series:
test_native_gem: { name: json, version: 1.8.6 }
"2.3":
openssl: openssl1.0
patches: [init_only_exports]
baseruby: none
use_libedit: true
install_doc: false
Expand All @@ -119,6 +126,7 @@ series:
test_native_gem: { name: json, version: 1.8.6 }
"2.4":
openssl: openssl1.1
patches: [init_only_exports]
baseruby: none # 2.4's configure rejects --with-baseruby=no
use_libedit: true
install_doc: false
Expand All @@ -131,6 +139,7 @@ series:
test_native_gem: { name: msgpack, version: 1.4.2 }
"2.5":
openssl: openssl1.1
patches: [init_only_exports]
baseruby: "no"
use_libedit: true
install_doc: false
Expand All @@ -143,6 +152,7 @@ series:
test_native_gem: { name: msgpack, version: 1.4.2 }
"2.6":
openssl: openssl1.1
patches: [init_only_exports]
baseruby: "no"
use_libedit: true
install_doc: false
Expand All @@ -156,6 +166,7 @@ series:
test_native_gem: { name: msgpack, version: 1.4.2 }
"2.7":
openssl: openssl1.1
patches: [init_only_exports]
baseruby: "no"
readline_ext: false # readline.rb falls back to reline from 2.7
install_doc: false
Expand All @@ -169,6 +180,7 @@ series:
test_native_gem: { name: msgpack, version: 1.4.2 }
"3.0":
openssl: openssl1.1 # 3.0's openssl extension predates OpenSSL 3
patches: [init_only_exports]
readline_ext: false
install_doc: false
extra_out_ext: [gdbm, dbm]
Expand All @@ -179,6 +191,7 @@ series:
test_native_gem: { name: msgpack, version: 1.4.2 }
"3.1":
openssl: openssl1.1 # OpenSSL 3 is supported but this keeps 2.4–3.1 uniform
patches: [init_only_exports]
readline_ext: false
install_doc: false
extra_out_ext: [gdbm, dbm]
Expand Down
Loading