diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py index 4c20685b51c..da96c8b6d40 100755 --- a/contrib/devtools/security-check.py +++ b/contrib/devtools/security-check.py @@ -248,7 +248,9 @@ BASE_MACHO = [ CHECKS = { lief.EXE_FORMATS.ELF: { - lief.ARCHITECTURES.X86: BASE_ELF + [('CONTROL_FLOW', check_ELF_CONTROL_FLOW), ('FORTIFY', check_ELF_FORTIFY)], + # no imported fortified funcs if we are fully static, fortification is still applied + # the check could be changed to include all symbols later + lief.ARCHITECTURES.X86: BASE_ELF + [('CONTROL_FLOW', check_ELF_CONTROL_FLOW)], lief.ARCHITECTURES.ARM: BASE_ELF + [('FORTIFY', check_ELF_FORTIFY)], lief.ARCHITECTURES.ARM64: BASE_ELF + [('FORTIFY', check_ELF_FORTIFY)], lief.ARCHITECTURES.PPC: BASE_ELF + [('FORTIFY', check_ELF_FORTIFY)], diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index 564f1db5ac0..7a88d5193a9 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -34,7 +34,7 @@ import lief MAX_VERSIONS = { 'GCC': (4,3,0), 'GLIBC': { - lief.ELF.ARCH.x86_64: (2,31), + lief.ELF.ARCH.x86_64: (0,0), lief.ELF.ARCH.ARM: (2,31), lief.ELF.ARCH.AARCH64:(2,31), lief.ELF.ARCH.PPC64: (2,31), @@ -47,14 +47,14 @@ MAX_VERSIONS = { # Ignore symbols that are exported as part of every executable IGNORE_EXPORTS = { 'environ', '_environ', '__environ', '_fini', '_init', 'stdin', -'stdout', 'stderr', +'stdout', 'stderr', '__libc_single_threaded', } # Expected linker-loader names can be found here: # 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", @@ -98,7 +98,6 @@ ELF_ALLOWED_LIBRARIES = { 'libpthread.so.0', # threading 'libm.so.6', # math library 'libatomic.so.1', -'ld-linux-x86-64.so.2', # 64-bit dynamic linker 'ld-linux.so.2', # 32-bit dynamic linker 'ld-linux-aarch64.so.1', # 64-bit ARM dynamic linker 'ld-linux-armhf.so.3', # 32-bit ARM dynamic linker @@ -219,6 +218,10 @@ def check_RUNPATH(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!') diff --git a/contrib/guix/libexec/build.sh b/contrib/guix/libexec/build.sh index 389706a8cf4..a4662a5e00c 100755 --- a/contrib/guix/libexec/build.sh +++ b/contrib/guix/libexec/build.sh @@ -142,10 +142,10 @@ export GUIX_LD_WRAPPER_DISABLE_RPATH=yes # 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 ;; @@ -176,7 +176,8 @@ make -C depends --jobs="$JOBS" HOST="$HOST" \ x86_64_linux_AR=x86_64-linux-gnu-gcc-ar \ 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 + x86_64_linux_STRIP=x86_64-linux-gnu-strip \ + NO_QT=1 # Don't bother with static case "$HOST" in *darwin*) @@ -225,6 +226,7 @@ esac # LDFLAGS case "$HOST" in + x86_64-linux-gnu) HOST_LDFLAGS=" -static-pie -static-libgcc -Wl,-O2" ;; *linux*) HOST_LDFLAGS="-Wl,--as-needed -Wl,--dynamic-linker=$glibc_dynamic_linker -static-libstdc++ -Wl,-O2" ;; *mingw*) HOST_LDFLAGS="-Wl,--no-insert-timestamp" ;; esac diff --git a/contrib/guix/libexec/prelude.bash b/contrib/guix/libexec/prelude.bash index 428fc41e739..6fa391f7cfb 100644 --- a/contrib/guix/libexec/prelude.bash +++ b/contrib/guix/libexec/prelude.bash @@ -51,7 +51,7 @@ fi time-machine() { # shellcheck disable=SC2086 guix time-machine --url=https://git.savannah.gnu.org/git/guix.git \ - --commit=53396a22afc04536ddf75d8f82ad2eafa5082725 \ + --commit=cc30ed170af04565da9b4127def353e7fdd4a489 \ --cores="$JOBS" \ --keep-failed \ --fallback \ diff --git a/contrib/guix/manifest.scm b/contrib/guix/manifest.scm index 4e7e9552182..0d0bcf336cf 100644 --- a/contrib/guix/manifest.scm +++ b/contrib/guix/manifest.scm @@ -455,7 +455,7 @@ inspecting signatures in Mach-O binaries.") (define-public glibc-2.31 (let ((commit "7b27c450c34563a28e634cccb399cd415e71ebfe")) (package - (inherit glibc) ;; 2.35 + (inherit glibc) ;; 2.39 (version "2.31") (source (origin (method git-fetch) @@ -466,7 +466,8 @@ inspecting signatures in Mach-O binaries.") (sha256 (base32 "017qdpr5id7ddb4lpkzj2li1abvw916m3fc6n7nw28z4h5qbv2n0")) - (patches (search-our-patches "glibc-guix-prefix.patch")))) + (patches (search-our-patches "glibc-guix-prefix.patch" + "glibc-riscv-jumptarget.patch")))) (arguments (substitute-keyword-arguments (package-arguments glibc) ((#:configure-flags flags) @@ -523,6 +524,37 @@ inspecting signatures in Mach-O binaries.") (description "Just sponge") (license license:gpl2+))) +(define-public glibc-2.40 + (let ((commit "d8e8342369831808b00324790c8809ba33408ee7")) + (package + (inherit glibc) ;; 2.35 + (version "2.40") + (source (origin + (method git-fetch) + (uri (git-reference + (url "https://sourceware.org/git/glibc.git") + (commit commit))) + (file-name (git-file-name "glibc" commit)) + (sha256 + (base32 + "1qb2gzg6jjmynscg4wczsa5x0avyxjdvh5yn4j9l4ppm4vqd0n61")) + (patches (search-our-patches "glibc-2.40-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", + "--enable-fortify-source", + "--enable-cet=yes", + "--enable-nscd=no", + "--enable-static-nss=yes", + "--disable-timezone-tools", + "--disable-profile", + "--disable-werror", + building-on)))))))) + (packages->manifest (append (list ;; The Basics @@ -560,6 +592,10 @@ inspecting signatures in Mach-O binaries.") nsis-x86_64 nss-certs osslsigncode)) + ((string-contains target "x86_64-linux-") + (list (list gcc-toolchain-12 "static") + (make-bitcoin-cross-toolchain target + #:base-libc glibc-2.40))) ((string-contains target "-linux-") (list bison pkg-config diff --git a/contrib/guix/patches/glibc-2.40-guix-prefix.patch b/contrib/guix/patches/glibc-2.40-guix-prefix.patch new file mode 100644 index 00000000000..d1783bcf454 --- /dev/null +++ b/contrib/guix/patches/glibc-2.40-guix-prefix.patch @@ -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 + diff --git a/contrib/guix/patches/glibc-riscv-jumptarget.patch b/contrib/guix/patches/glibc-riscv-jumptarget.patch new file mode 100644 index 00000000000..702959433d8 --- /dev/null +++ b/contrib/guix/patches/glibc-riscv-jumptarget.patch @@ -0,0 +1,57 @@ +commit 68389203832ab39dd0dbaabbc4059e7fff51c29b +Author: Fangrui Song +Date: Thu Oct 28 11:39:49 2021 -0700 + + riscv: Fix incorrect jal with HIDDEN_JUMPTARGET + + A non-local STV_DEFAULT defined symbol is by default preemptible in a + shared object. j/jal cannot target a preemptible symbol. On other + architectures, such a jump instruction either causes PLT [BZ #18822], or + if short-ranged, sometimes rejected by the linker (but not by GNU ld's + riscv port [ld PR/28509]). + + Use HIDDEN_JUMPTARGET to target a non-preemptible symbol instead. + + With this patch, ld.so and libc.so can be linked with LLD if source + files are compiled/assembled with -mno-relax/-Wa,-mno-relax. + + Acked-by: Palmer Dabbelt + Reviewed-by: Adhemerval Zanella + +Can be dropped when we are using glibc 2.35 or later. + +diff --git a/sysdeps/riscv/setjmp.S b/sysdeps/riscv/setjmp.S +index 0b92016b31..bec7ff80f4 100644 +--- a/sysdeps/riscv/setjmp.S ++++ b/sysdeps/riscv/setjmp.S +@@ -21,7 +21,7 @@ + + ENTRY (_setjmp) + li a1, 0 +- j __sigsetjmp ++ j HIDDEN_JUMPTARGET (__sigsetjmp) + END (_setjmp) + ENTRY (setjmp) + li a1, 1 +diff --git a/sysdeps/unix/sysv/linux/riscv/setcontext.S b/sysdeps/unix/sysv/linux/riscv/setcontext.S +index 9510518750..e44a68aad4 100644 +--- a/sysdeps/unix/sysv/linux/riscv/setcontext.S ++++ b/sysdeps/unix/sysv/linux/riscv/setcontext.S +@@ -95,6 +95,7 @@ LEAF (__setcontext) + 99: j __syscall_error + + END (__setcontext) ++libc_hidden_def (__setcontext) + weak_alias (__setcontext, setcontext) + + LEAF (__start_context) +@@ -108,7 +109,7 @@ LEAF (__start_context) + /* Invoke subsequent context if present, else exit(0). */ + mv a0, s2 + beqz s2, 1f +- jal __setcontext +-1: j exit ++ jal HIDDEN_JUMPTARGET (__setcontext) ++1: j HIDDEN_JUMPTARGET (exit) + + END (__start_context)