Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions pkgs/build-support/cc-wrapper/add-flags.sh
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
# `-B@out@/bin' forces cc to use ld-wrapper.sh when calling ld.
export NIX_CFLAGS_COMPILE="-B@out@/bin/ $NIX_CFLAGS_COMPILE"

# Export and assign separately in order that a failing $(..) will fail
# the script.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added back better comment without typo.


if [ -e @out@/nix-support/libc-cflags ]; then
export NIX_CFLAGS_COMPILE="$(cat @out@/nix-support/libc-cflags) $NIX_CFLAGS_COMPILE"
export NIX_CFLAGS_COMPILE
NIX_CFLAGS_COMPILE="$(< @out@/nix-support/libc-cflags) $NIX_CFLAGS_COMPILE"
fi

if [ -e @out@/nix-support/cc-cflags ]; then
export NIX_CFLAGS_COMPILE="$(cat @out@/nix-support/cc-cflags) $NIX_CFLAGS_COMPILE"
export NIX_CFLAGS_COMPILE
NIX_CFLAGS_COMPILE="$(< @out@/nix-support/cc-cflags) $NIX_CFLAGS_COMPILE"
fi

if [ -e @out@/nix-support/gnat-cflags ]; then
export NIX_GNATFLAGS_COMPILE="$(cat @out@/nix-support/gnat-cflags) $NIX_GNATFLAGS_COMPILE"
export NIX_GNATFLAGS_COMPILE
NIX_GNATFLAGS_COMPILE="$(< @out@/nix-support/gnat-cflags) $NIX_GNATFLAGS_COMPILE"
fi

if [ -e @out@/nix-support/libc-ldflags ]; then
export NIX_LDFLAGS+=" $(cat @out@/nix-support/libc-ldflags)"
export NIX_LDFLAGS
NIX_LDFLAGS+=" $(< @out@/nix-support/libc-ldflags)"
fi

if [ -e @out@/nix-support/cc-ldflags ]; then
export NIX_LDFLAGS+=" $(cat @out@/nix-support/cc-ldflags)"
export NIX_LDFLAGS
NIX_LDFLAGS+=" $(< @out@/nix-support/cc-ldflags)"
fi

if [ -e @out@/nix-support/libc-ldflags-before ]; then
export NIX_LDFLAGS_BEFORE="$(cat @out@/nix-support/libc-ldflags-before) $NIX_LDFLAGS_BEFORE"
export NIX_LDFLAGS_BEFORE
NIX_LDFLAGS_BEFORE="$(< @out@/nix-support/libc-ldflags-before) $NIX_LDFLAGS_BEFORE"
fi

export NIX_CC_WRAPPER_FLAGS_SET=1
30 changes: 22 additions & 8 deletions pkgs/build-support/cc-wrapper/add-hardening.sh
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
hardeningFlags=(fortify stackprotector pic strictoverflow format relro bindnow)
hardeningFlags+=("${hardeningEnable[@]}")
# Intentionally word-split in case 'hardeningEnable' is defined in Nix.
hardeningFlags+=(${hardeningEnable[@]})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semantics change, but all the flags are sans-whitespace so it seems fine.

hardeningCFlags=()
hardeningLDFlags=()
hardeningDisable=${hardeningDisable:-""}

hardeningDisable+=" @hardening_unsupported_flags@"
declare -A hardeningDisableMap

if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: Value of '$hardeningDisable': $hardeningDisable >&2; fi
# Intentionally word-split in case 'hardeningDisable' is defined in Nix. The
# array expansion also prevents undefined variables from causing trouble with
# `set -u`.
for flag in ${hardeningDisable[@]} @hardening_unsupported_flags@
do
hardeningDisableMap[$flag]=1
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is clearer than the regex stuff that was there before---and shellcheck said the regex stuff was done wrong anyways such that only string literals would match.

done

if [[ ! $hardeningDisable =~ "all" ]]; then
if [[ -n "$NIX_DEBUG" ]]; then echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2; fi
if [[ -n "$NIX_DEBUG" ]]; then
printf 'HARDENING: disabled flags:' >&2
(( "${#hardeningDisableMap[@]}" )) && printf ' %q' "${!hardeningDisableMap[@]}" >&2
echo >&2
fi

if [[ -z "${hardeningDisableMap[all]}" ]]; then
if [[ -n "$NIX_DEBUG" ]]; then
echo 'HARDENING: Is active (not completely disabled with "all" flag)' >&2;
fi
for flag in "${hardeningFlags[@]}"
do
if [[ ! "${hardeningDisable}" =~ "$flag" ]]; then
if [[ -z "${hardeningDisableMap[$flag]}" ]]; then
case $flag in
fortify)
if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling fortify >&2; fi
hardeningCFlags+=('-O2' '-D_FORTIFY_SOURCE=2')
;;
stackprotector)
if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling stackprotector >&2; fi
hardeningCFlags+=('-fstack-protector-strong' '--param ssp-buffer-size=4')
hardeningCFlags+=('-fstack-protector-strong' '--param' 'ssp-buffer-size=4')
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

N.B. bugs like this weren't being caught because extra word splitting on arrays.

;;
pie)
if [[ -n "$NIX_DEBUG" ]]; then echo HARDENING: enabling CFlags -fPIE >&2; fi
Expand Down
82 changes: 42 additions & 40 deletions pkgs/build-support/cc-wrapper/cc-wrapper.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
#! @shell@ -e
#! @shell@
set -e -o pipefail
shopt -s nullglob

path_backup="$PATH"
if [ -n "@coreutils_bin@" ]; then
PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin"

# That @-vars are substituted separately from bash evaluation makes
# shellcheck think this, and others like it, are useless conditionals.
# shellcheck disable=SC2157
if [[ -n "@coreutils_bin@" && -n "@gnugrep_bin@" ]]; then
PATH="@coreutils_bin@/bin:@gnugrep_bin@/bin"
fi

if [ -n "$NIX_CC_WRAPPER_START_HOOK" ]; then
Expand All @@ -19,16 +26,17 @@ source @out@/nix-support/utils.sh
# For instance, figure out if linker flags should be passed.
# GCC prints annoying warnings when they are not needed.
dontLink=0
getVersion=0
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was unused.

nonFlagArgs=0
# shellcheck disable=SC2193
[[ "@prog@" = *++ ]] && isCpp=1 || isCpp=0
cppInclude=1

expandResponseParams "$@"
n=0
while [ $n -lt ${#params[*]} ]; do
declare -i n=0
nParams=${#params[@]}
while [ "$n" -lt "$nParams" ]; do
p=${params[n]}
p2=${params[$((n+1))]}
p2=${params[n+1]}
if [ "$p" = -c ]; then
dontLink=1
elif [ "$p" = -S ]; then
Expand All @@ -55,10 +63,10 @@ while [ $n -lt ${#params[*]} ]; do
nonFlagArgs=1
elif [ "$p" = -m32 ]; then
if [ -e @out@/nix-support/dynamic-linker-m32 ]; then
NIX_LDFLAGS+=" -dynamic-linker $(cat @out@/nix-support/dynamic-linker-m32)"
NIX_LDFLAGS+=" -dynamic-linker $(< @out@/nix-support/dynamic-linker-m32)"
fi
fi
n=$((n + 1))
n+=1
done

# If we pass a flag like -Wl, then gcc will call the linker unless it
Expand All @@ -71,26 +79,27 @@ if [ "$nonFlagArgs" = 0 ]; then
fi

# Optionally filter out paths not refering to the store.
if [ "$NIX_ENFORCE_PURITY" = 1 -a -n "$NIX_STORE" ]; then
if [[ "$NIX_ENFORCE_PURITY" = 1 && -n "$NIX_STORE" ]]; then
rest=()
n=0
while [ $n -lt ${#params[*]} ]; do
nParams=${#params[@]}
declare -i n=0
while [ "$n" -lt "$nParams" ]; do
p=${params[n]}
p2=${params[$((n+1))]}
p2=${params[n+1]}
if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then
skip $p
skip "${p:2}"
elif [ "$p" = -L ] && badPath "$p2"; then
n=$((n + 1)); skip $p2
n+=1; skip "$p2"
elif [ "${p:0:3}" = -I/ ] && badPath "${p:2}"; then
skip $p
skip "${p:2}"
elif [ "$p" = -I ] && badPath "$p2"; then
n=$((n + 1)); skip $p2
n+=1; skip "$p2"
elif [ "$p" = -isystem ] && badPath "$p2"; then
n=$((n + 1)); skip $p2
n+=1; skip "$p2"
else
rest+=("$p")
fi
n=$((n + 1))
n+=1
done
params=("${rest[@]}")
fi
Expand All @@ -99,11 +108,11 @@ fi
# Clear march/mtune=native -- they bring impurity.
if [ "$NIX_ENFORCE_NO_NATIVE" = 1 ]; then
rest=()
for i in "${params[@]}"; do
if [[ "$i" = -m*=native ]]; then
skip $i
for p in "${params[@]}"; do
if [[ "$p" = -m*=native ]]; then
skip "$p"
else
rest+=("$i")
rest+=("$p")
fi
done
params=("${rest[@]}")
Expand All @@ -116,23 +125,22 @@ if [[ "$isCpp" = 1 ]]; then
NIX_CFLAGS_LINK+=" $NIX_CXXSTDLIB_LINK"
fi

LD=@ldPath@/ld
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be the unwrapped ld, which seems wrong.

source @out@/nix-support/add-hardening.sh

# Add the flags for the C compiler proper.
extraAfter=($NIX_CFLAGS_COMPILE ${hardeningCFlags[@]})
extraAfter=($NIX_CFLAGS_COMPILE "${hardeningCFlags[@]}")
extraBefore=()

if [ "$dontLink" != 1 ]; then

# Add the flags that should only be passed to the compiler when
# linking.
extraAfter+=($NIX_CFLAGS_LINK ${hardeningLDFlags[@]})
extraAfter+=($NIX_CFLAGS_LINK "${hardeningLDFlags[@]}")

# Add the flags that should be passed to the linker (and prevent
# `ld-wrapper' from adding NIX_LDFLAGS again).
for i in $NIX_LDFLAGS_BEFORE; do
extraBefore=(${extraBefore[@]} "-Wl,$i")
extraBefore+=("-Wl,$i")
done
for i in $NIX_LDFLAGS; do
if [ "${i:0:3}" = -L/ ]; then
Expand All @@ -155,23 +163,17 @@ fi

# Optionally print debug info.
if [ -n "$NIX_DEBUG" ]; then
echo "original flags to @prog@:" >&2
for i in "${params[@]}"; do
echo " $i" >&2
done
echo "extraBefore flags to @prog@:" >&2
for i in ${extraBefore[@]}; do
echo " $i" >&2
done
echo "extraAfter flags to @prog@:" >&2
for i in ${extraAfter[@]}; do
echo " $i" >&2
done
echo "extra flags before to @prog@:" >&2
printf " %q\n" "${extraBefore[@]}" >&2
echo "original flags to @prog@:" >&2
printf " %q\n" "${params[@]}" >&2
echo "extra flags after to @prog@:" >&2
printf " %q\n" "${extraAfter[@]}" >&2
fi

if [ -n "$NIX_CC_WRAPPER_EXEC_HOOK" ]; then
source "$NIX_CC_WRAPPER_EXEC_HOOK"
fi

PATH="$path_backup"
exec @prog@ ${extraBefore[@]} "${params[@]}" "${extraAfter[@]}"
exec @prog@ "${extraBefore[@]}" "${params[@]}" "${extraAfter[@]}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semantics change, but the old version was a mistake. I fixed a hardening flag bug uncovered by this; hope there aren't others.

@orivej did something the same fix for ld-wrapper, and I guess it was fine there?

81 changes: 43 additions & 38 deletions pkgs/build-support/cc-wrapper/gnat-wrapper.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
#! @shell@ -e
#! @shell@
set -e -o pipefail
shopt -s nullglob

path_backup="$PATH"

# phase separation makes this look useless
# shellcheck disable=SC2157
if [ -n "@coreutils_bin@" ]; then
PATH="@coreutils_bin@/bin"
PATH="@coreutils_bin@/bin"
fi

if [ -n "$NIX_GNAT_WRAPPER_START_HOOK" ]; then
Expand All @@ -18,7 +24,6 @@ source @out@/nix-support/utils.sh
# Figure out if linker flags should be passed. GCC prints annoying
# warnings when they are not needed.
dontLink=0
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a dead variable, but used in commented code, so I guess I'll leave it for now.

getVersion=0
nonFlagArgs=0

for i in "$@"; do
Expand All @@ -30,7 +35,7 @@ for i in "$@"; do
nonFlagArgs=1
elif [ "$i" = -m32 ]; then
if [ -e @out@/nix-support/dynamic-linker-m32 ]; then
NIX_LDFLAGS="$NIX_LDFLAGS -dynamic-linker $(cat @out@/nix-support/dynamic-linker-m32)"
NIX_LDFLAGS+=" -dynamic-linker $(< @out@/nix-support/dynamic-linker-m32)"
fi
fi
done
Expand All @@ -47,24 +52,20 @@ fi

# Optionally filter out paths not refering to the store.
params=("$@")
if [ "$NIX_ENFORCE_PURITY" = 1 -a -n "$NIX_STORE" ]; then
if [[ "$NIX_ENFORCE_PURITY" = 1 && -n "$NIX_STORE" ]]; then
rest=()
n=0
while [ $n -lt ${#params[*]} ]; do
p=${params[n]}
p2=${params[$((n+1))]}
for p in "${params[@]}"; do
if [ "${p:0:3}" = -L/ ] && badPath "${p:2}"; then
skip $p
skip "${p:2}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the "skip" thing does say "bad path", but not knowing what flag it came from is strictly less useful. I'm conflicted.

elif [ "${p:0:3}" = -I/ ] && badPath "${p:2}"; then
skip $p
skip "${p:2}"
elif [ "${p:0:4}" = -aI/ ] && badPath "${p:3}"; then
skip $p
skip "${p:2}"
elif [ "${p:0:4}" = -aO/ ] && badPath "${p:3}"; then
skip $p
skip "${p:2}"
else
rest+=("$p")
fi
n=$((n + 1))
done
params=("${rest[@]}")
fi
Expand All @@ -73,11 +74,11 @@ fi
# Clear march/mtune=native -- they bring impurity.
if [ "$NIX_ENFORCE_NO_NATIVE" = 1 ]; then
rest=()
for i in "${params[@]}"; do
if [[ "$i" = -m*=native ]]; then
skip $i
for p in "${params[@]}"; do
if [[ "$p" = -m*=native ]]; then
skip "$p"
else
rest+=("$i")
rest+=("$p")
fi
done
params=("${rest[@]}")
Expand All @@ -88,35 +89,39 @@ fi
extraAfter=($NIX_GNATFLAGS_COMPILE)
extraBefore=()

if [ "`basename $0`x" = "gnatmakex" ]; then
extraBefore=("--GNATBIND=@out@/bin/gnatbind --GNATLINK=@out@/bin/gnatlink ")
if [ "$(basename "$0")x" = "gnatmakex" ]; then
extraBefore=("--GNATBIND=@out@/bin/gnatbind" "--GNATLINK=@out@/bin/gnatlink ")
fi

# Add the flags that should be passed to the linker (and prevent
# `ld-wrapper' from adding NIX_LDFLAGS again).
#for i in $NIX_LDFLAGS_BEFORE; do
# extraBefore=(${extraBefore[@]} "-largs $i")
#done
#if [ "$dontLink" != 1 ]; then
# # Add the flags that should be passed to the linker (and prevent
# # `ld-wrapper' from adding NIX_LDFLAGS again).
# for i in $NIX_LDFLAGS_BEFORE; do
# extraBefore+=("-largs" "$i")
# done
# for i in $NIX_LDFLAGS; do
# if [ "${i:0:3}" = -L/ ]; then
# extraAfter+=("$i")
# else
# extraAfter+=("-largs" "$i")
# fi
# done
# export NIX_LDFLAGS_SET=1
#fi

# Optionally print debug info.
if [ -n "$NIX_DEBUG" ]; then
echo "original flags to @prog@:" >&2
for i in "${params[@]}"; do
echo " $i" >&2
done
echo "extraBefore flags to @prog@:" >&2
for i in ${extraBefore[@]}; do
echo " $i" >&2
done
echo "extraAfter flags to @prog@:" >&2
for i in ${extraAfter[@]}; do
echo " $i" >&2
done
echo "extra flags before to @prog@:" >&2
printf " %q\n" "${extraBefore[@]}" >&2
echo "original flags to @prog@:" >&2
printf " %q\n" "${params[@]}" >&2
echo "extra flags after to @prog@:" >&2
printf " %q\n" "${extraAfter[@]}" >&2
fi

if [ -n "$NIX_GNAT_WRAPPER_EXEC_HOOK" ]; then
source "$NIX_GNAT_WRAPPER_EXEC_HOOK"
fi

PATH="$path_backup"
exec @prog@ ${extraBefore[@]} "${params[@]}" ${extraAfter[@]}
exec @prog@ "${extraBefore[@]}" "${params[@]}" "${extraAfter[@]}"
Loading