Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] guix: produce a fully -static-pie bitcoind #25573

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,8 @@ if test "$TARGET_OS" != "windows"; then
AX_CHECK_COMPILE_FLAG([-fPIC], [PIC_FLAGS="-fPIC"])
fi

AX_CHECK_LINK_FLAG([-Wl,-z,pack-relative-relocs], [HARDENED_LDFLAGS="$HARDENED_LDFLAGS -Wl,-z,pack-relative-relocs"], [], [$LDFLAG_WERROR])

if test "$use_hardening" != "no"; then
use_hardening=yes
AX_CHECK_COMPILE_FLAG([-Wstack-protector], [HARDENED_CXXFLAGS="$HARDENED_CXXFLAGS -Wstack-protector"])
Expand Down
6 changes: 5 additions & 1 deletion contrib/devtools/symbol-check.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
# https://sourceware.org/glibc/wiki/ABIList?action=recall&rev=16
ELF_INTERPRETER_NAMES: dict[lief.ELF.ARCH, dict[lief.ENDIANNESS, str]] = {
lief.ELF.ARCH.x86_64: {
lief.ENDIANNESS.LITTLE: "/lib64/ld-linux-x86-64.so.2",
lief.ENDIANNESS.LITTLE: "",
},
lief.ELF.ARCH.ARM: {
lief.ENDIANNESS.LITTLE: "/lib/ld-linux-armhf.so.3",
Expand Down Expand Up @@ -214,6 +214,10 @@ def check_exported_symbols(binary) -> bool:

def check_ELF_libraries(binary) -> bool:
ok: bool = True

if binary.header.machine_type == lief.ELF.ARCH.x86_64:
return len(binary.libraries) == 0

for library in binary.libraries:
if library not in ELF_ALLOWED_LIBRARIES:
print(f'{filename}: {library} is not in ALLOWED_LIBRARIES!')
Expand Down
8 changes: 4 additions & 4 deletions contrib/guix/libexec/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,10 @@ esac

# Determine the correct value for -Wl,--dynamic-linker for the current $HOST
case "$HOST" in
x86_64-linux-gnu) ;;
*linux*)
glibc_dynamic_linker=$(
case "$HOST" in
x86_64-linux-gnu) echo /lib64/ld-linux-x86-64.so.2 ;;
arm-linux-gnueabihf) echo /lib/ld-linux-armhf.so.3 ;;
aarch64-linux-gnu) echo /lib/ld-linux-aarch64.so.1 ;;
riscv64-linux-gnu) echo /lib/ld-linux-riscv64-lp64d.so.1 ;;
Expand Down Expand Up @@ -200,7 +200,8 @@ make -C depends --jobs="$JOBS" HOST="$HOST" \
x86_64_linux_RANLIB=x86_64-linux-gnu-gcc-ranlib \
x86_64_linux_NM=x86_64-linux-gnu-gcc-nm \
x86_64_linux_STRIP=x86_64-linux-gnu-strip \
FORCE_USE_SYSTEM_CLANG=1
FORCE_USE_SYSTEM_CLANG=1 \
NO_QT=1


###########################
Expand Down Expand Up @@ -242,6 +243,7 @@ esac

# LDFLAGS
case "$HOST" in
x86_64-linux-gnu) HOST_LDFLAGS="-static-libgcc -static-pie -Wl,-O2" ;; # static-libgcc needed for configure
*linux*) HOST_LDFLAGS="-Wl,--as-needed -Wl,--dynamic-linker=$glibc_dynamic_linker -static-libstdc++ -Wl,-O2" ;;
*mingw*) HOST_LDFLAGS="-Wl,--no-insert-timestamp" ;;
esac
Expand Down Expand Up @@ -274,8 +276,6 @@ mkdir -p "$DISTSRC"
# Build Bitcoin Core
make --jobs="$JOBS" ${V:+V=1}

# Check that symbol/security checks tools are sane.
make test-security-check ${V:+V=1}
# Perform basic security checks on a series of executables.
make -C src --jobs=1 check-security ${V:+V=1}
# Check that executables only contain allowed version symbols.
Expand Down
2 changes: 1 addition & 1 deletion contrib/guix/libexec/prelude.bash
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fi
time-machine() {
# shellcheck disable=SC2086
guix time-machine --url=https://git.savannah.gnu.org/git/guix.git \
--commit=dc4842797bfdc5f9f3f5f725bf189c2b68bd6b5a \
--commit=a8353e9d6b34fd8d42d2e8f14ce844849fe9c293 \
--cores="$JOBS" \
--keep-failed \
--fallback \
Expand Down
43 changes: 36 additions & 7 deletions contrib/guix/manifest.scm
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,14 @@ chain for " target " development."))
(home-page (package-home-page xgcc))
(license (package-license xgcc)))))

(define base-gcc gcc-12)
(define base-gcc gcc-13)
(define base-linux-kernel-headers linux-libre-headers-6.1)

(define* (make-bitcoin-cross-toolchain target
#:key
(base-gcc-for-libc linux-base-gcc)
(base-kernel-headers base-linux-kernel-headers)
(base-libc glibc-2.27)
(base-libc glibc-2.39)
(base-gcc linux-base-gcc))
"Convenience wrapper around MAKE-CROSS-TOOLCHAIN with default values
desirable for building Bitcoin Core release binaries."
Expand Down Expand Up @@ -480,6 +480,35 @@ inspecting signatures in Mach-O binaries.")
(("^install-others =.*$")
(string-append "install-others = " out "/etc/rpc\n"))))))))))))

(define-public glibc-2.39
(package
(inherit glibc) ;; 2.35
(version "2.39")
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://sourceware.org/git/glibc.git")
(commit "1b9c1a0047fb26a65a9b2a7b8cd977243f7d353c")))
(file-name (git-file-name "glibc" "1b9c1a0047fb26a65a9b2a7b8cd977243f7d353c"))
(sha256
(base32
"1h27p9c4bnb9z74mj307w5x3i9n4irhxmkg11qrnclyz25cbm5r8"))
(patches (search-our-patches "glibc-2.39-guix-prefix.patch"))))
(arguments
(substitute-keyword-arguments (package-arguments glibc)
((#:configure-flags flags)
`(append ,flags
;; https://www.gnu.org/software/libc/manual/html_node/Configuring-and-compiling.html
(list "--enable-stack-protector=all",
"--enable-bind-now",
"--disable-werror",
"--enable-fortify-source=yes",
"--enable-cet=yes",
"--enable-nscd=no",
"--enable-static-nss=yes",
"--enable-static-pie=yes",
building-on)))))))

(packages->manifest
(append
(list ;; The Basics
Expand Down Expand Up @@ -517,17 +546,17 @@ inspecting signatures in Mach-O binaries.")
python-lief)
(let ((target (getenv "HOST")))
(cond ((string-suffix? "-mingw32" target)
(list ;; Native GCC 12 toolchain
gcc-toolchain-12
(list ;; Native GCC 13 toolchain
gcc-toolchain-13
zip
(make-mingw-pthreads-cross-toolchain "x86_64-w64-mingw32")
nsis-x86_64
nss-certs
osslsigncode))
((string-contains target "-linux-")
(list ;; Native GCC 12 toolchain
gcc-toolchain-12
(list gcc-toolchain-12 "static")
(list ;; Native GCC 13 toolchain
gcc-toolchain-13
(list gcc-toolchain-13 "static")
(make-bitcoin-cross-toolchain target)))
((string-contains target "darwin")
(list ;; Native GCC 11 toolchain
Expand Down
47 changes: 47 additions & 0 deletions contrib/guix/patches/glibc-2.39-guix-prefix.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Without ffile-prefix-map, the debug symbols will contain paths for the
guix store which will include the hashes of each package. However, the
hash for the same package will differ when on different architectures.
In order to be reproducible regardless of the architecture used to build
the package, map all guix store prefixes to something fixed, e.g. /usr.

--- a/Makeconfig
+++ b/Makeconfig
@@ -1074,6 +1074,10 @@ CPPFLAGS-.o = $(pic-default)
CFLAGS-.o = $(filter %frame-pointer,$(+cflags)) $(pie-default)
CFLAGS-.o += $(call elide-fortify-source,.o,$(routines_no_fortify))
CFLAGS-.o += $(call elide-fortify-source,_chk.o,$(routines_no_fortify))
+
+# Map Guix store paths to /usr
+CFLAGS-.o += `find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;`
+
libtype.o := lib%.a
object-suffixes += .o
ifeq (yes,$(build-shared))
diff --git a/iconv/Makefile b/iconv/Makefile
index afb3fb7bdb..5acee345e0 100644
--- a/iconv/Makefile
+++ b/iconv/Makefile
@@ -65,6 +65,9 @@ CFLAGS-gconv_cache.c += -DGCONV_DIR='"$(gconvdir)"'
CFLAGS-gconv_conf.c += -DGCONV_PATH='"$(gconvdir)"'
CFLAGS-iconvconfig.c += -DGCONV_PATH='"$(gconvdir)"' -DGCONV_DIR='"$(gconvdir)"'

+# Map Guix store paths to /usr
+CFLAGS-.c += `find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;`
+
# Set libof-* for each routine.
cpp-srcs-left := $(iconv_prog-modules) $(iconvconfig-modules)
lib := iconvprogs
diff --git a/posix/Makefile b/posix/Makefile
index 3d368b91f6..d79d8fb648 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -590,6 +590,9 @@ CFLAGS-execlp.os = -fomit-frame-pointer
CFLAGS-nanosleep.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-fork.c = $(libio-mtsafe) $(config-cflags-wno-ignored-attributes)

+# Map Guix store paths to /usr
+CFLAGS-.c += `find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;`
+
tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
--none random --col --color --colour