From 3d6869aa9f73464215b12c82a91e6aaec55c520f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Tue, 8 Sep 2026 04:36:33 +0300 Subject: [PATCH 01/15] supautils: match prod debug symbols and glibc symbol versions --- .../supautils-strtol-glibc-compat.patch | 29 +++++++++++++++++++ nix/ext/supautils.nix | 4 +++ 2 files changed, 33 insertions(+) create mode 100644 nix/ext/patches/supautils-strtol-glibc-compat.patch diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch new file mode 100644 index 0000000000..6e8292d8f5 --- /dev/null +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -0,0 +1,29 @@ +diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c +index 18e5aee..d5172a3 100644 +--- a/src/constrained_extensions.c ++++ b/src/constrained_extensions.c +@@ -9,6 +9,24 @@ + #include "constrained_extensions.h" + #include "utils.h" + ++// Force GLIBC_2.17 (atoi's inlined strtol, dlsym/dlvsym) for older-glibc hosts. ++#if defined(__linux__) && defined(__GLIBC__) ++extern void *dlvsym(void *handle, const char *symbol, const char *version); ++extern void *dlsym(void *handle, const char *symbol); ++__asm__(".symver dlvsym,dlvsym@GLIBC_2.17"); ++__asm__(".symver dlsym,dlsym@GLIBC_2.17"); ++static int ++_supautils_compat_atoi(const char *nptr) ++{ ++ long (*fn)(const char *, char **, int) = ++ (long (*)(const char *, char **, int)) dlvsym((void *) 0, "strtol", "GLIBC_2.17"); ++ if (!fn) ++ fn = (long (*)(const char *, char **, int)) dlsym((void *) 0, "strtol"); ++ return fn ? (int) fn(nptr, NULL, 10) : 0; ++} ++#define atoi(a) _supautils_compat_atoi(a) ++#endif ++ + static JSON_ACTION_RETURN_TYPE json_array_start(void *state) { + json_constrained_extension_parse_state *parse = state; + diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index 361cd1b741..bd16c8919c 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -12,6 +12,8 @@ stdenv.mkDerivation rec { buildInputs = [ postgresql ]; + dontStrip = true; + src = fetchFromGitHub { owner = "supabase"; repo = pname; @@ -19,6 +21,8 @@ stdenv.mkDerivation rec { hash = "sha256-O2zVVVf2OFTCc4BYHuGJ67odU0TwMnTJQuz9uk+a4/0="; }; + patches = [ ./patches/supautils-strtol-glibc-compat.patch ]; + installPhase = '' mkdir -p $out/lib From 274e75a5de38ddd18e464a7d77564df48c643b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Wed, 9 Sep 2026 01:32:21 +0300 Subject: [PATCH 02/15] supautils: drop unversioned dlsym fallback in glibc-compat shim The fallback silently re-resolved strtol to its default (newest) version if the GLIBC_2.17 lookup ever failed, defeating the whole point of the patch. GLIBC_2.17 is strtol's only version node in modern glibc (the 2.38 one is a distinct symbol, __isoc23_strtol, from the C23 variant of atoi/stdlib.h), and it's already comfortably below the project's glibc 2.31 floor, so no version bump is needed here. Co-Authored-By: Claude Sonnet 5 --- nix/ext/patches/supautils-strtol-glibc-compat.patch | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch index 6e8292d8f5..935dcaf835 100644 --- a/nix/ext/patches/supautils-strtol-glibc-compat.patch +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -1,24 +1,22 @@ diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c -index 18e5aee..d5172a3 100644 +index 18e5aee..4eced0b 100644 --- a/src/constrained_extensions.c +++ b/src/constrained_extensions.c -@@ -9,6 +9,24 @@ +@@ -9,6 +9,22 @@ #include "constrained_extensions.h" #include "utils.h" -+// Force GLIBC_2.17 (atoi's inlined strtol, dlsym/dlvsym) for older-glibc hosts. ++// Modern glibc's inlined atoi() calls __isoc23_strtol@GLIBC_2.38 instead of ++// strtol. That symbol doesn't exist on older hosts, so resolve plain ++// strtol@GLIBC_2.17 (its only version node) directly instead. +#if defined(__linux__) && defined(__GLIBC__) +extern void *dlvsym(void *handle, const char *symbol, const char *version); -+extern void *dlsym(void *handle, const char *symbol); +__asm__(".symver dlvsym,dlvsym@GLIBC_2.17"); -+__asm__(".symver dlsym,dlsym@GLIBC_2.17"); +static int +_supautils_compat_atoi(const char *nptr) +{ + long (*fn)(const char *, char **, int) = + (long (*)(const char *, char **, int)) dlvsym((void *) 0, "strtol", "GLIBC_2.17"); -+ if (!fn) -+ fn = (long (*)(const char *, char **, int)) dlsym((void *) 0, "strtol"); + return fn ? (int) fn(nptr, NULL, 10) : 0; +} +#define atoi(a) _supautils_compat_atoi(a) From 66af52362324121a10d42e4328ba5f29336ac097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Wed, 9 Sep 2026 01:35:26 +0300 Subject: [PATCH 03/15] supautils: shorten glibc-compat comment Co-Authored-By: Claude Sonnet 5 --- nix/ext/patches/supautils-strtol-glibc-compat.patch | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch index 935dcaf835..970c441501 100644 --- a/nix/ext/patches/supautils-strtol-glibc-compat.patch +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -1,14 +1,12 @@ diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c -index 18e5aee..4eced0b 100644 +index 18e5aee..64757d7 100644 --- a/src/constrained_extensions.c +++ b/src/constrained_extensions.c -@@ -9,6 +9,22 @@ +@@ -9,6 +9,20 @@ #include "constrained_extensions.h" #include "utils.h" -+// Modern glibc's inlined atoi() calls __isoc23_strtol@GLIBC_2.38 instead of -+// strtol. That symbol doesn't exist on older hosts, so resolve plain -+// strtol@GLIBC_2.17 (its only version node) directly instead. ++// atoi's inlined strtol resolves to __isoc23_strtol@GLIBC_2.38; pin strtol@GLIBC_2.17 instead. +#if defined(__linux__) && defined(__GLIBC__) +extern void *dlvsym(void *handle, const char *symbol, const char *version); +__asm__(".symver dlvsym,dlvsym@GLIBC_2.17"); From cf5b0c1b9ac79c67ed5ebddd4421175c4a5989a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Wed, 9 Sep 2026 01:59:40 +0300 Subject: [PATCH 04/15] supautils: fix glibc-compat version pin for x86_64 GLIBC_2.17 isn't a valid version node for dlvsym/strtol on x86_64 (verified via objdump against the real glibc: x86_64's nodes are 2.2.5/2.34, since that symbol's ABI never changed at 2.17 there). It only worked on aarch64 because aarch64 support was added in glibc 2.17, making that its earliest possible tag. Pin per-arch: 2.2.5 on x86_64, 2.17 on aarch64. Co-Authored-By: Claude Sonnet 5 --- .../supautils-strtol-glibc-compat.patch | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch index 970c441501..1e3bf484c0 100644 --- a/nix/ext/patches/supautils-strtol-glibc-compat.patch +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -1,20 +1,27 @@ diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c -index 18e5aee..64757d7 100644 +index 18e5aee..cdfb63f 100644 --- a/src/constrained_extensions.c +++ b/src/constrained_extensions.c -@@ -9,6 +9,20 @@ +@@ -9,6 +9,27 @@ #include "constrained_extensions.h" #include "utils.h" -+// atoi's inlined strtol resolves to __isoc23_strtol@GLIBC_2.38; pin strtol@GLIBC_2.17 instead. -+#if defined(__linux__) && defined(__GLIBC__) ++// atoi's inlined strtol resolves to __isoc23_strtol@GLIBC_2.38; pin strtol's oldest ++// version node instead (2.2.5 on x86_64, 2.17 on aarch64, which glibc added support ++// for at 2.17, so it has no earlier tag). ++#if defined(__linux__) && defined(__GLIBC__) && (defined(__x86_64__) || defined(__aarch64__)) ++# if defined(__x86_64__) ++# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.2.5" ++# else ++# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.17" ++# endif +extern void *dlvsym(void *handle, const char *symbol, const char *version); -+__asm__(".symver dlvsym,dlvsym@GLIBC_2.17"); ++__asm__(".symver dlvsym,dlvsym@" SUPAUTILS_GLIBC_COMPAT_VER); +static int +_supautils_compat_atoi(const char *nptr) +{ + long (*fn)(const char *, char **, int) = -+ (long (*)(const char *, char **, int)) dlvsym((void *) 0, "strtol", "GLIBC_2.17"); ++ (long (*)(const char *, char **, int)) dlvsym((void *) 0, "strtol", SUPAUTILS_GLIBC_COMPAT_VER); + return fn ? (int) fn(nptr, NULL, 10) : 0; +} +#define atoi(a) _supautils_compat_atoi(a) From b73056b267788c059f1567ead35734a4855147ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 04:26:38 +0300 Subject: [PATCH 05/15] supautils: use single glibc symver for both arches GLIBC_2.17 exists on both x86_64 and aarch64 (aarch64 support starts there), so one version node covers both instead of branching per-arch. Co-Authored-By: Claude Sonnet 5 --- nix/ext/patches/supautils-strtol-glibc-compat.patch | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch index 1e3bf484c0..8828e2cc87 100644 --- a/nix/ext/patches/supautils-strtol-glibc-compat.patch +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -2,19 +2,12 @@ diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c index 18e5aee..cdfb63f 100644 --- a/src/constrained_extensions.c +++ b/src/constrained_extensions.c -@@ -9,6 +9,27 @@ +@@ -9,6 +9,20 @@ #include "constrained_extensions.h" #include "utils.h" -+// atoi's inlined strtol resolves to __isoc23_strtol@GLIBC_2.38; pin strtol's oldest -+// version node instead (2.2.5 on x86_64, 2.17 on aarch64, which glibc added support -+// for at 2.17, so it has no earlier tag). +#if defined(__linux__) && defined(__GLIBC__) && (defined(__x86_64__) || defined(__aarch64__)) -+# if defined(__x86_64__) -+# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.2.5" -+# else -+# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.17" -+# endif ++# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.17" +extern void *dlvsym(void *handle, const char *symbol, const char *version); +__asm__(".symver dlvsym,dlvsym@" SUPAUTILS_GLIBC_COMPAT_VER); +static int From e5b49db8dbf704c8a52be084e3354fb4fb191f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 05:50:29 +0300 Subject: [PATCH 06/15] Revert: keep per-arch glibc symver for dlvsym MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit x86_64 CI failed link with "no symbol version section for versioned symbol dlvsym@GLIBC_2.17" — x86_64 glibc's dlvsym has no 2.17 version node (it's 2.2.5 there); aarch64's dlvsym only exists from 2.17 onward. No shared version <=2.31 covers dlvsym on both arches, so the original per-arch split is required. Co-Authored-By: Claude Sonnet 5 --- nix/ext/patches/supautils-strtol-glibc-compat.patch | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch index 8828e2cc87..72b8436195 100644 --- a/nix/ext/patches/supautils-strtol-glibc-compat.patch +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -2,12 +2,18 @@ diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c index 18e5aee..cdfb63f 100644 --- a/src/constrained_extensions.c +++ b/src/constrained_extensions.c -@@ -9,6 +9,20 @@ +@@ -9,6 +9,26 @@ #include "constrained_extensions.h" #include "utils.h" - + ++// dlvsym's earliest version node differs per arch: 2.2.5 on x86_64, 2.17 on ++// aarch64 (glibc's aarch64 port starts at 2.17, so it has no earlier node). +#if defined(__linux__) && defined(__GLIBC__) && (defined(__x86_64__) || defined(__aarch64__)) -+# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.17" ++# if defined(__x86_64__) ++# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.2.5" ++# else ++# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.17" ++# endif +extern void *dlvsym(void *handle, const char *symbol, const char *version); +__asm__(".symver dlvsym,dlvsym@" SUPAUTILS_GLIBC_COMPAT_VER); +static int From a15d645b45adbb90b481bb35b75df3317b880649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 05:53:36 +0300 Subject: [PATCH 07/15] supautils: drop explanatory comment from glibc-compat patch Co-Authored-By: Claude Sonnet 5 --- nix/ext/patches/supautils-strtol-glibc-compat.patch | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nix/ext/patches/supautils-strtol-glibc-compat.patch b/nix/ext/patches/supautils-strtol-glibc-compat.patch index 72b8436195..06f846b91f 100644 --- a/nix/ext/patches/supautils-strtol-glibc-compat.patch +++ b/nix/ext/patches/supautils-strtol-glibc-compat.patch @@ -2,12 +2,10 @@ diff --git a/src/constrained_extensions.c b/src/constrained_extensions.c index 18e5aee..cdfb63f 100644 --- a/src/constrained_extensions.c +++ b/src/constrained_extensions.c -@@ -9,6 +9,26 @@ +@@ -9,6 +9,24 @@ #include "constrained_extensions.h" #include "utils.h" -+// dlvsym's earliest version node differs per arch: 2.2.5 on x86_64, 2.17 on -+// aarch64 (glibc's aarch64 port starts at 2.17, so it has no earlier node). +#if defined(__linux__) && defined(__GLIBC__) && (defined(__x86_64__) || defined(__aarch64__)) +# if defined(__x86_64__) +# define SUPAUTILS_GLIBC_COMPAT_VER "GLIBC_2.2.5" From b357e3e3beac308d8c08144aac9d77668c7cf37d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 07:10:02 +0300 Subject: [PATCH 08/15] supautils/gatekeeper: strip RPATH, split debug info from runtime closure Both .so files are dlopen'd into a process that already links glibc, so the nix-store glibc RPATH patchelf bakes in is unnecessary and risks a version mismatch. dontStrip also leaked the full build-time toolchain (gcc, postgresql, systemd-dev) into supautils' runtime closure via embedded debug-info paths; separateDebugInfo keeps the symbols without that (closure: 666 MiB -> 78.9 MiB). Co-Authored-By: Claude Sonnet 5 --- nix/ext/supautils.nix | 7 ++++++- nix/packages/gatekeeper.nix | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index 833a505a44..7f4651857e 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -3,6 +3,7 @@ stdenv, fetchFromGitHub, postgresql, + patchelf, }: stdenv.mkDerivation rec { @@ -11,8 +12,9 @@ stdenv.mkDerivation rec { version = "3.4.3"; buildInputs = [ postgresql ]; + nativeBuildInputs = lib.optionals stdenv.isLinux [ patchelf ]; - dontStrip = true; + separateDebugInfo = true; src = fetchFromGitHub { owner = "supabase"; @@ -27,6 +29,9 @@ stdenv.mkDerivation rec { mkdir -p $out/lib install -D *${postgresql.dlSuffix} -t $out/lib + '' + + lib.optionalString stdenv.isLinux '' + patchelf --remove-rpath $out/lib/supautils${postgresql.dlSuffix} ''; meta = with lib; { diff --git a/nix/packages/gatekeeper.nix b/nix/packages/gatekeeper.nix index 5ec53c74e9..d0c84c7812 100644 --- a/nix/packages/gatekeeper.nix +++ b/nix/packages/gatekeeper.nix @@ -37,11 +37,14 @@ pkgs.stdenv.mkDerivation { version = "1.0.5"; buildInputs = [ upstream-gatekeeper ]; + nativeBuildInputs = [ pkgs.patchelf ]; dontUnpack = true; installPhase = '' mkdir -p $out/lib/security/ cp ${upstream-gatekeeper}/lib/security/pam_jit_pg.so $out/lib/security/pam_jit_pg.so + chmod +w $out/lib/security/pam_jit_pg.so + patchelf --remove-rpath $out/lib/security/pam_jit_pg.so ''; } From 720d0edcc817d1c8043ceb72ffbd646491c9d05b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 07:36:30 +0300 Subject: [PATCH 09/15] supautils/gatekeeper: actually purge the glibc RPATH, not just its dynamic tag patchelf --remove-rpath only clears the DT_RUNPATH entry; the store-path string itself stays live in .dynstr, so nix's reference scanner still pulled glibc/gcc/postgresql into the runtime closure. NIX_DONT_SET_RPATH stops the linker writing it in the first place; zeroing the remaining PGXS-injected rpath bytes covers what that doesn't catch. supautils closure: 666 MiB -> 80.7 KiB, no glibc reference. gatekeeper closure: 74.6 MiB -> 9.7 MiB, no glibc/pam reference (residual is Go's own tzdata/mailcap/iana-etc path constants, unrelated to dlopen). Co-Authored-By: Claude Sonnet 5 --- nix/ext/supautils.nix | 9 ++++++++- nix/packages/gatekeeper.nix | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index 7f4651857e..c5d035c444 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -15,6 +15,7 @@ stdenv.mkDerivation rec { nativeBuildInputs = lib.optionals stdenv.isLinux [ patchelf ]; separateDebugInfo = true; + NIX_DONT_SET_RPATH = stdenv.isLinux; src = fetchFromGitHub { owner = "supabase"; @@ -31,7 +32,13 @@ stdenv.mkDerivation rec { install -D *${postgresql.dlSuffix} -t $out/lib '' + lib.optionalString stdenv.isLinux '' - patchelf --remove-rpath $out/lib/supautils${postgresql.dlSuffix} + so=$out/lib/supautils${postgresql.dlSuffix} + rp=$(patchelf --print-rpath "$so") + patchelf --remove-rpath "$so" + if [ -n "$rp" ]; then + off=$(grep -aboF "$rp" "$so" | head -1 | cut -d: -f1) + dd if=/dev/zero of="$so" bs=1 seek="$off" count="''${#rp}" conv=notrunc status=none + fi ''; meta = with lib; { diff --git a/nix/packages/gatekeeper.nix b/nix/packages/gatekeeper.nix index d0c84c7812..5c721d155b 100644 --- a/nix/packages/gatekeeper.nix +++ b/nix/packages/gatekeeper.nix @@ -16,6 +16,7 @@ let vendorHash = null; buildInputs = [ pkgs.pam ]; + NIX_DONT_SET_RPATH = true; buildPhase = '' runHook preBuild @@ -45,6 +46,12 @@ pkgs.stdenv.mkDerivation { mkdir -p $out/lib/security/ cp ${upstream-gatekeeper}/lib/security/pam_jit_pg.so $out/lib/security/pam_jit_pg.so chmod +w $out/lib/security/pam_jit_pg.so - patchelf --remove-rpath $out/lib/security/pam_jit_pg.so + so=$out/lib/security/pam_jit_pg.so + rp=$(patchelf --print-rpath "$so") + patchelf --remove-rpath "$so" + if [ -n "$rp" ]; then + off=$(grep -aboF "$rp" "$so" | head -1 | cut -d: -f1) + dd if=/dev/zero of="$so" bs=1 seek="$off" count="''${#rp}" conv=notrunc status=none + fi ''; } From b244932bc902bf31937619ca0ca4b4b832d97cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 07:48:57 +0300 Subject: [PATCH 10/15] supautils/gatekeeper: replace dd byte-surgery with nix's own reference-discard mechanism unsafeDiscardReferences is the nix-native way to tell the closure scanner to ignore a spurious match, instead of manually zeroing bytes in .dynstr. gatekeeper never needed it in the first place: NIX_DONT_SET_RPATH already left its rpath empty, so the removal step there was dead code. Co-Authored-By: Claude Sonnet 5 --- nix/ext/supautils.nix | 11 ++++------- nix/packages/gatekeeper.nix | 8 +------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index c5d035c444..bd8cd7b5f4 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -17,6 +17,9 @@ stdenv.mkDerivation rec { separateDebugInfo = true; NIX_DONT_SET_RPATH = stdenv.isLinux; + __structuredAttrs = true; + unsafeDiscardReferences.out = stdenv.isLinux; + src = fetchFromGitHub { owner = "supabase"; repo = pname; @@ -32,13 +35,7 @@ stdenv.mkDerivation rec { install -D *${postgresql.dlSuffix} -t $out/lib '' + lib.optionalString stdenv.isLinux '' - so=$out/lib/supautils${postgresql.dlSuffix} - rp=$(patchelf --print-rpath "$so") - patchelf --remove-rpath "$so" - if [ -n "$rp" ]; then - off=$(grep -aboF "$rp" "$so" | head -1 | cut -d: -f1) - dd if=/dev/zero of="$so" bs=1 seek="$off" count="''${#rp}" conv=notrunc status=none - fi + patchelf --remove-rpath $out/lib/supautils${postgresql.dlSuffix} ''; meta = with lib; { diff --git a/nix/packages/gatekeeper.nix b/nix/packages/gatekeeper.nix index 5c721d155b..ccdadfdafb 100644 --- a/nix/packages/gatekeeper.nix +++ b/nix/packages/gatekeeper.nix @@ -46,12 +46,6 @@ pkgs.stdenv.mkDerivation { mkdir -p $out/lib/security/ cp ${upstream-gatekeeper}/lib/security/pam_jit_pg.so $out/lib/security/pam_jit_pg.so chmod +w $out/lib/security/pam_jit_pg.so - so=$out/lib/security/pam_jit_pg.so - rp=$(patchelf --print-rpath "$so") - patchelf --remove-rpath "$so" - if [ -n "$rp" ]; then - off=$(grep -aboF "$rp" "$so" | head -1 | cut -d: -f1) - dd if=/dev/zero of="$so" bs=1 seek="$off" count="''${#rp}" conv=notrunc status=none - fi + patchelf --remove-rpath $out/lib/security/pam_jit_pg.so ''; } From 0ca31f9f1d31347f6af5cf1868a8ecf8cdb78d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 08:09:57 +0300 Subject: [PATCH 11/15] supautils: drop patchelf/unsafeDiscardReferences, NIX_DONT_SET_RPATH alone is enough Verified empirically: with NIX_DONT_SET_RPATH set, PGXS's own link step already writes an empty RUNPATH, not one patchelf needs to clean up after. No dead strings, no discarded references, same 80.7 KiB closure. Co-Authored-By: Claude Sonnet 5 --- nix/ext/supautils.nix | 8 -------- 1 file changed, 8 deletions(-) diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index bd8cd7b5f4..2c351a82e6 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -3,7 +3,6 @@ stdenv, fetchFromGitHub, postgresql, - patchelf, }: stdenv.mkDerivation rec { @@ -12,14 +11,10 @@ stdenv.mkDerivation rec { version = "3.4.3"; buildInputs = [ postgresql ]; - nativeBuildInputs = lib.optionals stdenv.isLinux [ patchelf ]; separateDebugInfo = true; NIX_DONT_SET_RPATH = stdenv.isLinux; - __structuredAttrs = true; - unsafeDiscardReferences.out = stdenv.isLinux; - src = fetchFromGitHub { owner = "supabase"; repo = pname; @@ -33,9 +28,6 @@ stdenv.mkDerivation rec { mkdir -p $out/lib install -D *${postgresql.dlSuffix} -t $out/lib - '' - + lib.optionalString stdenv.isLinux '' - patchelf --remove-rpath $out/lib/supautils${postgresql.dlSuffix} ''; meta = with lib; { From 5f6aa9df348d8b01f80cd092e1bf00d89206cf9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 08:18:30 +0300 Subject: [PATCH 12/15] gatekeeper: drop no-op patchelf step NIX_DONT_SET_RPATH already leaves the RUNPATH empty; the removal call never had anything to do. Co-Authored-By: Claude Sonnet 5 --- nix/packages/gatekeeper.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/nix/packages/gatekeeper.nix b/nix/packages/gatekeeper.nix index ccdadfdafb..de3124f59b 100644 --- a/nix/packages/gatekeeper.nix +++ b/nix/packages/gatekeeper.nix @@ -38,14 +38,11 @@ pkgs.stdenv.mkDerivation { version = "1.0.5"; buildInputs = [ upstream-gatekeeper ]; - nativeBuildInputs = [ pkgs.patchelf ]; dontUnpack = true; installPhase = '' mkdir -p $out/lib/security/ cp ${upstream-gatekeeper}/lib/security/pam_jit_pg.so $out/lib/security/pam_jit_pg.so - chmod +w $out/lib/security/pam_jit_pg.so - patchelf --remove-rpath $out/lib/security/pam_jit_pg.so ''; } From 0876b82060859779f57ac872eaae20a86b928a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 08:33:13 +0300 Subject: [PATCH 13/15] gatekeeper: guard NIX_DONT_SET_RPATH by isLinux, matching supautils gatekeeper builds on darwin too (unlike supautils, which is already Linux-gated at the site-env.nix call site), and the flag is a no-op there either way -- Mach-O linking always embeds full dylib paths regardless. Scope it the same as supautils for consistency. Co-Authored-By: Claude Sonnet 5 --- nix/packages/gatekeeper.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/packages/gatekeeper.nix b/nix/packages/gatekeeper.nix index de3124f59b..8f3db4cfd2 100644 --- a/nix/packages/gatekeeper.nix +++ b/nix/packages/gatekeeper.nix @@ -16,7 +16,7 @@ let vendorHash = null; buildInputs = [ pkgs.pam ]; - NIX_DONT_SET_RPATH = true; + NIX_DONT_SET_RPATH = pkgs.stdenv.isLinux; buildPhase = '' runHook preBuild From 754855fad92a2fa71d11e7402f0848c77cedc796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 08:36:39 +0300 Subject: [PATCH 14/15] supautils/gatekeeper: comment why NIX_DONT_SET_RPATH is set Co-Authored-By: Claude Sonnet 5 --- nix/ext/supautils.nix | 2 ++ nix/packages/gatekeeper.nix | 2 ++ 2 files changed, 4 insertions(+) diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index 2c351a82e6..c7d03e7720 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -13,6 +13,8 @@ stdenv.mkDerivation rec { buildInputs = [ postgresql ]; separateDebugInfo = true; + + # dlopen'd into postgres, which already links glibc NIX_DONT_SET_RPATH = stdenv.isLinux; src = fetchFromGitHub { diff --git a/nix/packages/gatekeeper.nix b/nix/packages/gatekeeper.nix index 8f3db4cfd2..2147aad272 100644 --- a/nix/packages/gatekeeper.nix +++ b/nix/packages/gatekeeper.nix @@ -16,6 +16,8 @@ let vendorHash = null; buildInputs = [ pkgs.pam ]; + + # dlopen'd into PAM, which already links glibc NIX_DONT_SET_RPATH = pkgs.stdenv.isLinux; buildPhase = '' From 51aceed77c5fc99e7a25db20d34dac6e66bacb1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 18 Sep 2026 08:42:11 +0300 Subject: [PATCH 15/15] supautils/gatekeeper: say "libs" not "glibc" in comment, gatekeeper needs more than that Co-Authored-By: Claude Sonnet 5 --- nix/ext/supautils.nix | 2 +- nix/packages/gatekeeper.nix | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nix/ext/supautils.nix b/nix/ext/supautils.nix index c7d03e7720..c1c2a4e846 100644 --- a/nix/ext/supautils.nix +++ b/nix/ext/supautils.nix @@ -14,7 +14,7 @@ stdenv.mkDerivation rec { separateDebugInfo = true; - # dlopen'd into postgres, which already links glibc + # dlopen'd into postgres, which already links these libs NIX_DONT_SET_RPATH = stdenv.isLinux; src = fetchFromGitHub { diff --git a/nix/packages/gatekeeper.nix b/nix/packages/gatekeeper.nix index 2147aad272..f882b2931e 100644 --- a/nix/packages/gatekeeper.nix +++ b/nix/packages/gatekeeper.nix @@ -17,7 +17,7 @@ let buildInputs = [ pkgs.pam ]; - # dlopen'd into PAM, which already links glibc + # dlopen'd into PAM, which already links these libs NIX_DONT_SET_RPATH = pkgs.stdenv.isLinux; buildPhase = ''