diff --git a/pkgs/applications/networking/cluster/linkerd/generic.nix b/pkgs/applications/networking/cluster/linkerd/generic.nix index ef5835bcd6db..20f07da27e2b 100644 --- a/pkgs/applications/networking/cluster/linkerd/generic.nix +++ b/pkgs/applications/networking/cluster/linkerd/generic.nix @@ -31,11 +31,6 @@ buildGoModule rec { env GOFLAGS="" go generate ./jaeger/static env GOFLAGS="" go generate ./multicluster/static env GOFLAGS="" go generate ./viz/static - - # Necessary for building Musl - if [[ $NIX_HARDENING_ENABLE =~ "pie" ]]; then - export GOFLAGS="-buildmode=pie $GOFLAGS" - fi ''; tags = [ diff --git a/pkgs/build-support/go/module.nix b/pkgs/build-support/go/module.nix index c1c644e4294e..685f0071bc82 100644 --- a/pkgs/build-support/go/module.nix +++ b/pkgs/build-support/go/module.nix @@ -250,6 +250,9 @@ lib.extendMkDerivation { export GOPATH="$TMPDIR/go" export GOPROXY=off export GOSUMDB=off + if [ -f "$NIX_CC_FOR_TARGET/nix-support/dynamic-linker" ]; then + export GO_LDSO=$(cat $NIX_CC_FOR_TARGET/nix-support/dynamic-linker) + fi cd "$modRoot" '' + lib.optionalString (finalAttrs.vendorHash != null) '' @@ -266,13 +269,6 @@ lib.extendMkDerivation { } '' + '' - - # currently pie is only enabled by default in pkgsMusl - # this will respect the `hardening{Disable,Enable}` flags if set - if [[ $NIX_HARDENING_ENABLE =~ "pie" ]]; then - export GOFLAGS="-buildmode=pie $GOFLAGS" - fi - runHook postConfigure '' ); diff --git a/pkgs/development/compilers/go/1.24.nix b/pkgs/development/compilers/go/1.24.nix index 947123c5e170..8ee9c0f16725 100644 --- a/pkgs/development/compilers/go/1.24.nix +++ b/pkgs/development/compilers/go/1.24.nix @@ -64,6 +64,10 @@ stdenv.mkDerivation (finalAttrs: { }) ./remove-tools-1.11.patch ./go_no_vendor_checks-1.23.patch + ./go-env-go_ldso.patch + (replaceVars ./go-default-pie.patch { + inherit (stdenv.targetPlatform.go) GOARCH; + }) ]; inherit (stdenv.targetPlatform.go) GOOS GOARCH GOARM; @@ -99,6 +103,9 @@ stdenv.mkDerivation (finalAttrs: { buildPhase = '' runHook preBuild export GOCACHE=$TMPDIR/go-cache + if [ -f "$NIX_CC/nix-support/dynamic-linker" ]; then + export GO_LDSO=$(cat $NIX_CC/nix-support/dynamic-linker) + fi export PATH=$(pwd)/bin:$PATH @@ -106,6 +113,12 @@ stdenv.mkDerivation (finalAttrs: { # Independent from host/target, CC should produce code for the building system. # We only set it when cross-compiling. export CC=${buildPackages.stdenv.cc}/bin/cc + # Prefer external linker for cross when CGO is supported, since + # we haven't taught go's internal linker to pick the correct ELF + # interpreter for cross + # When CGO is not supported we rely on static binaries being built + # since they don't need an ELF interpreter + export GO_EXTLINK_ENABLED=${toString finalAttrs.CGO_ENABLED} ''} ulimit -a diff --git a/pkgs/development/compilers/go/1.25.nix b/pkgs/development/compilers/go/1.25.nix index b25f60b3d5ae..60a8c24ae425 100644 --- a/pkgs/development/compilers/go/1.25.nix +++ b/pkgs/development/compilers/go/1.25.nix @@ -10,8 +10,12 @@ buildPackages, pkgsBuildTarget, targetPackages, + # for testing testers, + runCommand, + bintools, skopeo, + clickhouse-backup, buildGo125Module, }: @@ -19,6 +23,7 @@ let goBootstrap = buildPackages.callPackage ./bootstrap122.nix { }; skopeoTest = skopeo.override { buildGoModule = buildGo125Module; }; + clickhouse-backupTest = clickhouse-backup.override { buildGoModule = buildGo125Module; }; # We need a target compiler which is still runnable at build time, # to handle the cross-building case where build != host == target @@ -69,6 +74,10 @@ stdenv.mkDerivation (finalAttrs: { }) ./remove-tools-1.11.patch ./go_no_vendor_checks-1.23.patch + ./go-env-go_ldso.patch + (replaceVars ./go-default-pie.patch { + inherit (stdenv.targetPlatform.go) GOARCH; + }) ]; inherit (stdenv.targetPlatform.go) GOOS GOARCH GOARM; @@ -104,6 +113,9 @@ stdenv.mkDerivation (finalAttrs: { buildPhase = '' runHook preBuild export GOCACHE=$TMPDIR/go-cache + if [ -f "$NIX_CC/nix-support/dynamic-linker" ]; then + export GO_LDSO=$(cat $NIX_CC/nix-support/dynamic-linker) + fi export PATH=$(pwd)/bin:$PATH @@ -111,6 +123,12 @@ stdenv.mkDerivation (finalAttrs: { # Independent from host/target, CC should produce code for the building system. # We only set it when cross-compiling. export CC=${buildPackages.stdenv.cc}/bin/cc + # Prefer external linker for cross when CGO is supported, since + # we haven't taught go's internal linker to pick the correct ELF + # interpreter for cross + # When CGO is not supported we rely on static binaries being built + # since they don't need an ELF interpreter + export GO_EXTLINK_ENABLED=${toString finalAttrs.CGO_ENABLED} ''} ulimit -a @@ -169,6 +187,23 @@ stdenv.mkDerivation (finalAttrs: { command = "go version"; version = "go${finalAttrs.version}"; }; + # Picked clickhouse-backup as a package that sets CGO_ENABLED=0 + # Running and outputting the right version proves a working ELF interpreter was picked + clickhouse-backup = testers.testVersion { package = clickhouse-backupTest; }; + clickhouse-backup-is-pie = runCommand "has-pie" { meta.broken = stdenv.hostPlatform.isStatic; } '' + ${lib.optionalString (!isCross) '' + if ${lib.getExe' bintools "readelf"} -p .comment ${lib.getExe clickhouse-backup} | grep -Fq "GCC: (GNU)"; then + echo "${lib.getExe clickhouse-backup} has a GCC .comment, but it should have used the internal go linker" + exit 1 + fi + ''} + if ${lib.getExe' bintools "readelf"} -h ${lib.getExe clickhouse-backup} | grep -q "Type:.*DYN"; then + touch $out + else + echo "ERROR: clickhouse-backup is NOT PIE" + exit 1 + fi + ''; }; }; diff --git a/pkgs/development/compilers/go/go-default-pie.patch b/pkgs/development/compilers/go/go-default-pie.patch new file mode 100644 index 000000000000..bce8d8dafd3d --- /dev/null +++ b/pkgs/development/compilers/go/go-default-pie.patch @@ -0,0 +1,13 @@ +diff --git a/src/internal/platform/supported.go b/src/internal/platform/supported.go +index f9706a6988..abac42d550 100644 +--- a/src/internal/platform/supported.go ++++ b/src/internal/platform/supported.go +@@ -249,7 +253,7 @@ func DefaultPIE(goos, goarch string, isRace bool) bool { + case "darwin": + return true + } +- return false ++ return goarch == "@GOARCH@" && BuildModeSupported("gc", "pie", goos, goarch) + } + + // ExecutableHasDWARF reports whether the linked executable includes DWARF diff --git a/pkgs/development/compilers/go/go-env-go_ldso.patch b/pkgs/development/compilers/go/go-env-go_ldso.patch new file mode 100644 index 000000000000..395b1dab3bf4 --- /dev/null +++ b/pkgs/development/compilers/go/go-env-go_ldso.patch @@ -0,0 +1,44 @@ +diff --git a/src/cmd/dist/buildruntime.go b/src/cmd/dist/buildruntime.go +index 87e8867176..dbb635011f 100644 +--- a/src/cmd/dist/buildruntime.go ++++ b/src/cmd/dist/buildruntime.go +@@ -62,7 +62,7 @@ func mkbuildcfg(file string) { + fmt.Fprintf(&buf, "const DefaultGORISCV64 = `%s`\n", goriscv64) + fmt.Fprintf(&buf, "const defaultGOEXPERIMENT = `%s`\n", goexperiment) + fmt.Fprintf(&buf, "const defaultGO_EXTLINK_ENABLED = `%s`\n", goextlinkenabled) +- fmt.Fprintf(&buf, "const defaultGO_LDSO = `%s`\n", defaultldso) ++ fmt.Fprintf(&buf, "const DefaultGO_LDSO = `%s`\n", defaultldso) + fmt.Fprintf(&buf, "const version = `%s`\n", findgoversion()) + fmt.Fprintf(&buf, "const defaultGOOS = runtime.GOOS\n") + fmt.Fprintf(&buf, "const defaultGOARCH = runtime.GOARCH\n") +diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go +index 6ff1d94383..147a7d91c9 100644 +--- a/src/cmd/link/internal/ld/elf.go ++++ b/src/cmd/link/internal/ld/elf.go +@@ -1927,8 +1927,12 @@ func asmbElf(ctxt *Link) { + sh.Flags = uint64(elf.SHF_ALLOC) + sh.Addralign = 1 + +- if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" { +- interpreter = buildcfg.GO_LDSO ++ if interpreter == "" { ++ if goLdso := os.Getenv("GO_LDSO"); goLdso != "" { ++ interpreter = goLdso ++ } else if buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH { ++ interpreter = buildcfg.DefaultGO_LDSO ++ } + } + + if interpreter == "" { +diff --git a/src/internal/buildcfg/cfg.go b/src/internal/buildcfg/cfg.go +index 7e4ee365df..8aaa70fb36 100644 +--- a/src/internal/buildcfg/cfg.go ++++ b/src/internal/buildcfg/cfg.go +@@ -33,7 +33,6 @@ var ( + GORISCV64 = goriscv64() + GOWASM = gowasm() + ToolTags = toolTags() +- GO_LDSO = defaultGO_LDSO + GOFIPS140 = gofips140() + Version = version + )