diff --git a/nix/checks.nix b/nix/checks.nix index 3bda47a906..26a9f096a2 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -925,6 +925,45 @@ postgresql_17_src ; psql_orioledb-17_exts_orioledb_debug = self'.legacyPackages.psql_orioledb-17.exts.orioledb.debug; + glibc-version-check = + let + checkScript = pkgs.writers.writeNuBin "check-glibc-version" ( + builtins.readFile ./tools/check-glibc-version.nu + ); + # supautils is dlopened into already-running legacy pre-nix postgres, so it needs a lower floor than an AMI build. + legacyPaths = [ + self'.legacyPackages.psql_15.exts.supautils + self'.legacyPackages.psql_17.exts.supautils + self'.legacyPackages."psql_orioledb-17".exts.supautils + ]; + # gatekeeper is dlopened by the base AMI's own system PAM stack, not postgres's nix + # closure, so it isn't covered by "core and extensions share one glibc" — pin it + # explicitly so a future nixpkgs glibc bump can't silently outrun the base image. + pamPaths = [ self'.packages.gatekeeper ]; + in + pkgs.runCommand "glibc-version-check" + { + nativeBuildInputs = [ pkgs.binutils ]; + inherit legacyPaths pamPaths; + } + '' + # 2.31: Ubuntu 20.04's glibc. + ${lib.getExe checkScript} 2.31 $legacyPaths + # 2.40: current core floor. + ${lib.getExe checkScript} 2.40 $pamPaths + touch $out + ''; + collation-version-check = + let + baseline = "glibc-2.40-66"; + actual = pkgs.glibc.name; + in + assert lib.assertMsg (actual == baseline) '' + glibc collation data changed: baseline is ${baseline}, build has ${actual}. + This can change collation versions and require a reindex. + If this bump has been reviewed for collation safety, update the baseline in nix/checks.nix to match. + ''; + pkgs.runCommand "collation-version-check" { } "touch $out"; }; }; } diff --git a/nix/tools/check-glibc-version.nu b/nix/tools/check-glibc-version.nu new file mode 100755 index 0000000000..d785dc2bd3 --- /dev/null +++ b/nix/tools/check-glibc-version.nu @@ -0,0 +1,38 @@ +#!/usr/bin/env nu + +def parse-version [] { + split row "." | each { into int } +} + +def is-elf []: path -> bool { + (open --raw $in | bytes at 0..<4) == ("\u{7f}ELF" | into binary) +} + +def max-glibc-version [path: path] { + ^objdump -T $path | complete | get stdout + | parse -r 'GLIBC_(?[0-9.]+)' | get ver + | each { parse-version } + | sort + | last +} + +# Fails if any file under the given paths requires a newer glibc than max_version. +def main [max_version: string, ...paths: path] { + let offenders = ( + $paths + | each { glob $"($in)/**/*" } | flatten + | where { ($in | path type) == file } + | where { is-elf } + | par-each { |f| { file: $f, version: (max-glibc-version $f) } } + | compact version + | where version > ($max_version | parse-version) + ) + + if ($offenders | is-empty) { + print $"glibc version OK \(<= ($max_version)\)" + exit 0 + } + + print ($offenders | update version { str join "." } | table --width 200) + exit 1 +}