cc-wrapper: don't set rpath on static-pie executables

This commit is contained in:
Jörg Thalheim 2021-05-22 13:55:47 +02:00
parent 61c74e1aee
commit 166948d479
4 changed files with 62 additions and 24 deletions

View file

@ -20,15 +20,23 @@ if [ -z "${NIX_BINTOOLS_WRAPPER_FLAGS_SET_@suffixSalt@:-}" ]; then
source @out@/nix-support/add-flags.sh source @out@/nix-support/add-flags.sh
fi fi
setDynamicLinker=1
# Optionally filter out paths not refering to the store. # Optionally filter out paths not refering to the store.
expandResponseParams "$@" expandResponseParams "$@"
# NIX_LINK_TYPE is set if ld has been called through our cc wrapper
if [[ -n "${NIX_LINK_TYPE_@suffixSalt@:-}" ]]; then
linkType=$NIX_LINK_TYPE_@suffixSalt@
else
linkType=$(checkLinkType "$@")
fi
if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}" if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
&& ( -z "$NIX_IGNORE_LD_THROUGH_GCC_@suffixSalt@" || -z "${NIX_LDFLAGS_SET_@suffixSalt@:-}" ) ]]; then && ( -z "$NIX_IGNORE_LD_THROUGH_GCC_@suffixSalt@" || -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ) ]]; then
rest=() rest=()
nParams=${#params[@]} nParams=${#params[@]}
declare -i n=0 declare -i n=0
while (( "$n" < "$nParams" )); do while (( "$n" < "$nParams" )); do
p=${params[n]} p=${params[n]}
p2=${params[n+1]:-} # handle `p` being last one p2=${params[n+1]:-} # handle `p` being last one
@ -48,11 +56,6 @@ if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
# Our ld is not built with sysroot support (Can we fix that?) # Our ld is not built with sysroot support (Can we fix that?)
: :
else else
if [[ "$p" = -static || "$p" = -static-pie ]]; then
# Using a dynamic linker for static binaries can lead to crashes.
# This was observed for rust binaries.
setDynamicLinker=0
fi
rest+=("$p") rest+=("$p")
fi fi
n+=1 n+=1
@ -61,22 +64,24 @@ if [[ "${NIX_ENFORCE_PURITY:-}" = 1 && -n "${NIX_STORE:-}"
params=(${rest+"${rest[@]}"}) params=(${rest+"${rest[@]}"})
fi fi
source @out@/nix-support/add-hardening.sh source @out@/nix-support/add-hardening.sh
extraAfter=() extraAfter=()
extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"}) extraBefore=(${hardeningLDFlags[@]+"${hardeningLDFlags[@]}"})
if [ -z "${NIX_LDFLAGS_SET_@suffixSalt@:-}" ]; then if [ -z "${NIX_LINK_TYPE_@suffixSalt@:-}" ]; then
extraAfter+=($NIX_LDFLAGS_@suffixSalt@) extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@))
extraBefore+=($NIX_LDFLAGS_BEFORE_@suffixSalt@) extraBefore+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@))
# By adding dynamic linker to extraBefore we allow the users set their # By adding dynamic linker to extraBefore we allow the users set their
# own dynamic linker as NIX_LD_FLAGS will override earlier set flags # own dynamic linker as NIX_LD_FLAGS will override earlier set flags
if [[ "$setDynamicLinker" = 1 && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
extraBefore+=("-dynamic-linker" "$NIX_DYNAMIC_LINKER_@suffixSalt@") extraBefore+=("-dynamic-linker" "$NIX_DYNAMIC_LINKER_@suffixSalt@")
fi fi
fi fi
extraAfter+=($NIX_LDFLAGS_AFTER_@suffixSalt@) extraAfter+=($(filterRpathFlags "$linkType" $NIX_LDFLAGS_AFTER_@suffixSalt@))
# These flags *must not* be pulled up to -Wl, flags, so they can't go in # These flags *must not* be pulled up to -Wl, flags, so they can't go in
# add-flags.sh. They must always be set, so must not be disabled by # add-flags.sh. They must always be set, so must not be disabled by
@ -173,7 +178,7 @@ do
prev="$p" prev="$p"
done done
if [[ "$link32" = "1" && "$setDynamicLinker" = 1 && -e "@out@/nix-support/dynamic-linker-m32" ]]; then if [[ "$link32" == "1" && "$linkType" == dynamic && -e "@out@/nix-support/dynamic-linker-m32" ]]; then
# We have an alternate 32-bit linker and we're producing a 32-bit ELF, let's # We have an alternate 32-bit linker and we're producing a 32-bit ELF, let's
# use it. # use it.
extraAfter+=( extraAfter+=(
@ -183,7 +188,7 @@ if [[ "$link32" = "1" && "$setDynamicLinker" = 1 && -e "@out@/nix-support/dynami
fi fi
# Add all used dynamic libraries to the rpath. # Add all used dynamic libraries to the rpath.
if [ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 ]; then if [[ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 && "$linkType" != static-pie ]]; then
# For each directory in the library search path (-L...), # For each directory in the library search path (-L...),
# see if it contains a dynamic library used by a -l... flag. If # see if it contains a dynamic library used by a -l... flag. If
# so, add the directory to the rpath. # so, add the directory to the rpath.

View file

@ -29,9 +29,10 @@ cc1=0
cxxInclude=1 cxxInclude=1
cxxLibrary=1 cxxLibrary=1
cInclude=1 cInclude=1
setDynamicLinker=1
expandResponseParams "$@" expandResponseParams "$@"
linkType=$(checkLinkType "$@")
declare -i n=0 declare -i n=0
nParams=${#params[@]} nParams=${#params[@]}
while (( "$n" < "$nParams" )); do while (( "$n" < "$nParams" )); do
@ -60,8 +61,6 @@ while (( "$n" < "$nParams" )); do
cxxInclude=0 cxxInclude=0
elif [ "$p" = -nostdinc++ ]; then elif [ "$p" = -nostdinc++ ]; then
cxxInclude=0 cxxInclude=0
elif [[ "$p" = -static || "$p" = -static-pie ]]; then
setDynamicLinker=0
elif [[ "$p" != -?* ]]; then elif [[ "$p" != -?* ]]; then
# A dash alone signifies standard input; it is not a flag # A dash alone signifies standard input; it is not a flag
nonFlagArgs=1 nonFlagArgs=1
@ -151,24 +150,24 @@ if [ "$dontLink" != 1 ]; then
# Add the flags that should only be passed to the compiler when # Add the flags that should only be passed to the compiler when
# linking. # linking.
extraAfter+=($NIX_CFLAGS_LINK_@suffixSalt@) extraAfter+=($(filterRpathFlags "$linkType" $NIX_CFLAGS_LINK_@suffixSalt@))
# Add the flags that should be passed to the linker (and prevent # Add the flags that should be passed to the linker (and prevent
# `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again). # `ld-wrapper' from adding NIX_LDFLAGS_@suffixSalt@ again).
for i in $NIX_LDFLAGS_BEFORE_@suffixSalt@; do for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_BEFORE_@suffixSalt@); do
extraBefore+=("-Wl,$i") extraBefore+=("-Wl,$i")
done done
if [[ "$setDynamicLinker" = 1 && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then if [[ "$linkType" == dynamic && -n "$NIX_DYNAMIC_LINKER_@suffixSalt@" ]]; then
extraBefore+=("-Wl,-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@") extraBefore+=("-Wl,-dynamic-linker=$NIX_DYNAMIC_LINKER_@suffixSalt@")
fi fi
for i in $NIX_LDFLAGS_@suffixSalt@; do for i in $(filterRpathFlags "$linkType" $NIX_LDFLAGS_@suffixSalt@); do
if [ "${i:0:3}" = -L/ ]; then if [ "${i:0:3}" = -L/ ]; then
extraAfter+=("$i") extraAfter+=("$i")
else else
extraAfter+=("-Wl,$i") extraAfter+=("-Wl,$i")
fi fi
done done
export NIX_LDFLAGS_SET_@suffixSalt@=1 export NIX_LINK_TYPE_@suffixSalt@=$linkType
fi fi
# As a very special hack, if the arguments are just `-v', then don't # As a very special hack, if the arguments are just `-v', then don't

View file

@ -123,3 +123,38 @@ expandResponseParams() {
fi fi
done done
} }
checkLinkType() {
local arg mode
type="dynamic"
for arg in "$@"; do
if [[ "$arg" = -static ]]; then
type="static"
elif [[ "$arg" = -static-pie ]]; then
type="static-pie"
fi
done
echo "$type"
}
# When building static-pie executables we cannot have rpath
# set. At least glibc requires rpath to be empty
filterRpathFlags() {
local linkType=$1 ret="" i
shift
if [[ "$linkType" == "static-pie" ]]; then
while [[ "$#" -gt 0 ]]; do
i="$1"; shift 1
if [[ "$i" == -rpath ]]; then
# also skip its argument
shift
else
ret+="$i "
fi
done
else
ret=$@
fi
echo $ret
}

View file

@ -35,8 +35,7 @@ in stdenv.mkDerivation {
printf "checking whether compiler builds valid static C binaries... " >&2 printf "checking whether compiler builds valid static C binaries... " >&2
$CC ${staticLibc} -static -o cc-static ${./cc-main.c} $CC ${staticLibc} -static -o cc-static ${./cc-main.c}
./cc-static ./cc-static
# our glibc does not have pie enabled yet. ${lib.optionalString (stdenv.cc.isGNU && lib.versionAtLeast (lib.getVersion stdenv.cc.name) "8.0.0") ''
${lib.optionalString (stdenv.hostPlatform.isMusl && stdenv.cc.isGNU) ''
printf "checking whether compiler builds valid static pie C binaries... " >&2 printf "checking whether compiler builds valid static pie C binaries... " >&2
$CC ${staticLibc} -static-pie -o cc-static-pie ${./cc-main.c} $CC ${staticLibc} -static-pie -o cc-static-pie ${./cc-main.c}
./cc-static-pie ./cc-static-pie