diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Probe the hardening flags in the release buildv2.4.0
Diffstat (limited to 'tools/release-build.sh')
-rwxr-xr-xtools/release-build.sh45
1 file changed, 43 insertions, 2 deletions
diff --git a/tools/release-build.sh b/tools/release-build.sh
index cfab7a2..b55fc43 100755
--- a/tools/release-build.sh
+++ b/tools/release-build.sh
@@ -32,17 +32,58 @@ esac
# there rather than requiring the caller to.
cd "$(dirname "$0")/.."
+CC=${CC:-cc}
+
+# Not every hardening flag exists on every toolchain, and an unknown one would
+# fail the build rather than be ignored, so each is compiled before it is used.
+supports() {
+ printf 'int main(void){return 0;}\n' >"$probe.c"
+ $CC $1 -o "$probe.out" "$probe.c" >/dev/null 2>&1
+}
+
+# An explicit template rather than -t, whose handling of a prefix differs
+# between the GNU and BSD versions.
+probe=$(mktemp "${TMPDIR:-/tmp}/cgit-probe.XXXXXX")
+trap 'rm -f "$probe" "$probe.c" "$probe.out"' EXIT
+
CFLAGS="-O2 -g -Wall \
-fstack-protector-strong \
- -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \
-fPIE \
-fno-plt"
+# Level 3 adds the bounds checks level 2 could not prove, and needs GCC 12 or
+# Clang 15. Fall back rather than lose fortification altogether.
+if supports "-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -O2"; then
+ CFLAGS="$CFLAGS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3"
+else
+ CFLAGS="$CFLAGS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2"
+fi
+
+# Makes a large stack frame touch each guard page rather than step over it.
+if supports "-fstack-clash-protection"; then
+ CFLAGS="$CFLAGS -fstack-clash-protection"
+fi
+
LDFLAGS="-pie \
-Wl,-z,relro,-z,now \
-Wl,-z,noexecstack"
+# These reach only the cgit objects, so git's own sources are not held to them.
+# -Wformat-security is an error because a non-literal format with no arguments
+# is never intentional.
+#
+# The shape that let a repository supply its own format string through
+# module-link was a non-literal *with* arguments, which only -Wformat-nonliteral
+# reports. It is left out here because it also fires on forwarding a va_list and
+# on local format constants, so it cannot be an error without false positives.
+# Worth running by hand when touching anything that formats:
+#
+# make cgit CGIT_EXTRA_CFLAGS=-Wformat-nonliteral
+#
+CGIT_EXTRA_CFLAGS="-Wformat -Wformat-security -Werror=format-security"
+
# A full rebuild so the bundled git objects pick up the same flags.
# cleanall also descends into vendor/git, which plain clean does not.
make cleanall
-exec make "$@" CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS"
+exec make "$@" CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" \
+ CGIT_EXTRA_CFLAGS="$CGIT_EXTRA_CFLAGS"