All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Stefan Sørensen" <stefan.sorensen@spectralink.com>
To: buildroot@busybox.net
Subject: [Buildroot] [RFC PATCH 2/2] core: Verify that hardening flags are used
Date: Thu,  3 May 2018 16:31:47 +0200	[thread overview]
Message-ID: <20180503143147.5301-3-stefan.sorensen@spectralink.com> (raw)
In-Reply-To: <20180503143147.5301-1-stefan.sorensen@spectralink.com>

This patch add a new package post install check that verifies that
configured hardening options are used.

Using the ELF notes added by the GCC annobin plugin, it verifies that
the following build options are used:
  * Stack protector
  * RELRO
  * FORTIFY_SOURCE
  * Optimization
  * Possition Independent Code/Executeable (-fPIC/-fPIE)

Signed-off-by: Stefan S?rensen <stefan.sorensen@spectralink.com>
---
 Config.in                      | 15 +++++++
 package/pkg-generic.mk         | 36 +++++++++++++++++
 support/scripts/check-hardened | 74 ++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+)
 create mode 100755 support/scripts/check-hardened

diff --git a/Config.in b/Config.in
index 6b5b2b043c..43fd15f3a2 100644
--- a/Config.in
+++ b/Config.in
@@ -826,6 +826,21 @@ endchoice
 
 comment "Fortify Source needs a glibc toolchain and optimization"
 	depends on (!BR2_TOOLCHAIN_USES_GLIBC || BR2_OPTIMIZE_0)
+
+
+config BR2_CHECK_HARDENING
+       bool "Verify hardened build"
+       depends on BR2_TOOLCHAIN_ANNOBIN_GCC_PLUGIN
+       depends on !BR2_SSP_REGULAR
+       depends on !BR2_FORTIFY_SOURCE_1
+       help
+         This option enables a packet post install step that verifies
+         that the selected hardning options was actually used during
+         the build.
+
+comment "Verifying hardened build needs the annobin GCC plugin and it not compatible with the regular stack protector and the conservative buffer overflow protector"
+	 depends on !BR2_TOOLCHAIN_ANNOBIN_GCC_PLUGIN || BR2_SSP_REGULAR || BR2_FORTIFY_SOURCE_1
+
 endmenu
 
 source "toolchain/Config.in"
diff --git a/package/pkg-generic.mk b/package/pkg-generic.mk
index a303dc2e07..9567d260bd 100644
--- a/package/pkg-generic.mk
+++ b/package/pkg-generic.mk
@@ -94,6 +94,42 @@ endef
 
 GLOBAL_INSTRUMENTATION_HOOKS += check_bin_arch
 
+ifeq ($(BR2_CHECK_HARDENING),y)
+# For now, no support for operator[] range check, control flow
+# enforcement, stack clash protection and control flow protection
+# hardening
+HARDENED_OPTS = -s operator -s cet -s clash -s cf
+
+ifneq ($(BR2_SSP_STRONG)$(BR2_SSP_ALL),y)
+HARDENED_OPTS += -s opt
+endif
+ifneq ($(BR2_OPTIMIZE_2)$(BR2_OPTIMIZE_3)$(BR2_OPTIMIZE_S),y)
+HARDENED_OPTS += -s opt
+endif
+ifneq ($(BR2_FORTIFY_SOURCE_2),y)
+HARDENED_OPTS += -s fort
+endif
+ifneq ($(BR2_RELRO_PARTIAL)$(BR2_RELRO_FULL),y)
+HARDENED_OPTS += -s relro
+endif
+ifneq ($(BR2_RELRO_FULL),y)
+HARDENED_OPTS += -s now -s pic
+endif
+
+define check_hardened
+	$(if $(filter end-install-target,$(1)-$(2)),\
+		support/scripts/check-hardened \
+			-p $(3) \
+			-l $(BUILD_DIR)/packages-file-list.txt \
+			$(foreach i,$($(PKG)_HARDENED_EXCLUDE),-i "$(i)") \
+			$(HARDENED_OPTS) \
+			-r $(TARGET_READELF) \
+			-h $(HARDENED_SH))
+endef
+
+GLOBAL_INSTRUMENTATION_HOOKS += check_hardened
+endif
+
 # This hook checks that host packages that need libraries that we build
 # have a proper DT_RPATH or DT_RUNPATH tag
 define check_host_rpath
diff --git a/support/scripts/check-hardened b/support/scripts/check-hardened
new file mode 100755
index 0000000000..8f4d6628cf
--- /dev/null
+++ b/support/scripts/check-hardened
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+
+# Heavily based on check-bin-arch
+
+# List of hardcoded paths that should be ignored, as they are
+# contain binaries for an architecture different from the
+# architecture of the target.
+declare -a IGNORES=(
+	# Skip firmware files, they could be ELF files for other
+	# architectures without hardening
+	"/lib/firmware"
+	"/usr/lib/firmware"
+
+	# Skip kernel modules
+	"/lib/modules"
+	"/usr/lib/modules"
+
+	# Skip files in /usr/share, several packages (qemu,
+	# pru-software-support) legitimately install ELF binaries that
+	# are not for the target architecture and are not hardened
+	"/usr/share"
+)
+
+declare -a skip
+
+while getopts p:l:h:r:i:s: OPT ; do
+	case "${OPT}" in
+	p) package="${OPTARG}";;
+	l) pkg_list="${OPTARG}";;
+	h) hardened="${OPTARG}";;
+	i)
+		# Ensure we do have single '/' as separators,
+		# and that we have a leading one.
+		pattern="$(sed -r -e 's:/+:/:g; s:^/*:/:;' <<<"${OPTARG}")"
+		IGNORES+=("${pattern}")
+		;;
+	r) readelf="${OPTARG}";;
+	s) skip+=("--skip=${OPTARG}");;
+	:) error "option '%s' expects a mandatory argument\n" "${OPTARG}";;
+	\?) error "unknown option '%s'\n" "${OPTARG}";;
+	esac
+done
+
+if test -z "${package}" -o -z "${pkg_list}" -o -z "${hardened}" ; then
+	echo "Usage: $0 -p <pkg> -l <pkg-file-list> -h <hardened> -r <readelf> [-i PATH ...]"
+	exit 1
+fi
+
+if [ ! -e ${hardened} ]; then
+	exit 0
+fi
+
+exitcode=0
+
+# Only split on new lines, for filenames-with-spaces
+IFS="
+"
+
+while read f; do
+	for ignore in "${IGNORES[@]}"; do
+		if [[ "${f}" =~ ^"${ignore}" ]]; then
+			continue 2
+		fi
+	done
+
+	# Only check regular files
+	if [[ ! -f "${TARGET_DIR}/${f}" ]]; then
+		continue
+	fi
+
+	${hardened} --readelf=${readelf} --ignore-unknown ${skip[*]} ${TARGET_DIR}${f} || exitcode=1
+done < <( sed -r -e "/^${package},\.(.+)$/!d; s//\1/;" ${pkg_list} )
+
+exit ${exitcode}
-- 
2.17.0

  parent reply	other threads:[~2018-05-03 14:31 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-03 14:31 [Buildroot] [RFC PATCH 0/2] Verify hardened builds Stefan Sørensen
2018-05-03 14:31 ` [Buildroot] [RFC PATCH 1/2] annobin: New package Stefan Sørensen
2018-05-03 22:13   ` Arnout Vandecappelle
2018-05-04  8:32     ` Sørensen, Stefan
2018-05-04 10:35       ` Arnout Vandecappelle
2019-02-06 15:04   ` Thomas Petazzoni
2019-02-06 15:27     ` Sørensen, Stefan
2019-02-06 15:40       ` Thomas Petazzoni
2018-05-03 14:31 ` Stefan Sørensen [this message]
2018-05-03 22:42   ` [Buildroot] [RFC PATCH 2/2] core: Verify that hardening flags are used Arnout Vandecappelle

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180503143147.5301-3-stefan.sorensen@spectralink.com \
    --to=stefan.sorensen@spectralink.com \
    --cc=buildroot@busybox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.