* [Buildroot] [PATCH v2 0/5] Hardening Wrapper Updates and Test
@ 2018-08-30 3:34 Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper Matt Weber
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Matt Weber @ 2018-08-30 3:34 UTC (permalink / raw)
To: buildroot
This series looks to complete the implementation and migration of
hardening related options to the compiler and (new) linker wrapper.
The series provides runtime testing for RELRO/SSP/FORTIFY.
v1 -> v2
- There were issues when I started regression testing where
packages where providing multiple pie/pic/shared args on
a single call of gcc/ld.
Signed-off-by: Matt Weber <matthew.weber@rockwellcollins.com>
CC: Jan Kundr?t <jan.kundrat@cesnet.cz>
CC: Stefan S?rensen <stefan.sorensen@spectralink.com>
Matt Weber (5):
toolchain/toolchain-wrapper: add link wrapper
toolchain/toolchain-wrapper: add BR2_RELRO_FULL support
toolchain/toolchain-wrapper: add BR2_SSP_* support
toolchain/toolchain-wrapper: add BR2_FORTIFY_SOURCE_* support
support/testing/tests/core: SSP & hardening flags
.gitlab-ci.yml | 6 +
package/Makefile.in | 19 +-
package/gcc/gcc.mk | 12 +-
support/testing/tests/core/test_hardening.py | 110 +++++++++
.../toolchain-external/pkg-toolchain-external.mk | 12 +-
toolchain/toolchain-wrapper-linker.c | 273 +++++++++++++++++++++
toolchain/toolchain-wrapper.c | 58 ++++-
toolchain/toolchain-wrapper.mk | 24 ++
8 files changed, 495 insertions(+), 19 deletions(-)
create mode 100644 support/testing/tests/core/test_hardening.py
create mode 100644 toolchain/toolchain-wrapper-linker.c
--
1.9.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper
2018-08-30 3:34 [Buildroot] [PATCH v2 0/5] Hardening Wrapper Updates and Test Matt Weber
@ 2018-08-30 3:34 ` Matt Weber
2018-08-30 7:53 ` Thomas Petazzoni
2018-08-30 3:34 ` [Buildroot] [PATCH v2 2/5] toolchain/toolchain-wrapper: add BR2_RELRO_FULL support Matt Weber
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Matt Weber @ 2018-08-30 3:34 UTC (permalink / raw)
To: buildroot
- Updates symlink creation int/ext toolchain
- Adds new source file for link wrapper with build/install
Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
---
package/gcc/gcc.mk | 12 +-
.../toolchain-external/pkg-toolchain-external.mk | 12 +-
toolchain/toolchain-wrapper-linker.c | 248 +++++++++++++++++++++
toolchain/toolchain-wrapper.mk | 6 +
4 files changed, 276 insertions(+), 2 deletions(-)
create mode 100644 toolchain/toolchain-wrapper-linker.c
diff --git a/package/gcc/gcc.mk b/package/gcc/gcc.mk
index 1ae9b7e..2b4ce33 100644
--- a/package/gcc/gcc.mk
+++ b/package/gcc/gcc.mk
@@ -262,7 +262,9 @@ HOST_GCC_COMMON_CONF_OPTS += \
--with-long-double-128
endif
-HOST_GCC_COMMON_TOOLCHAIN_WRAPPER_ARGS += -DBR_CROSS_PATH_SUFFIX='".br_real"'
+HOST_GCC_COMMON_TOOLCHAIN_WRAPPER_ARGS += \
+ -DBR_CROSS_PATH_SUFFIX='".br_real"' \
+ -DBR_CROSS_PATH_LD_SUFFIX='".br_real"'
# For gcc-initial, we need to tell gcc that the C library will be
# providing the ssp support, as it can't guess it since the C library
@@ -334,6 +336,14 @@ define HOST_GCC_INSTALL_WRAPPER_AND_SIMPLE_SYMLINKS
ln -sf toolchain-wrapper $(ARCH)-linux$${i##$(GNU_TARGET_NAME)}; \
ln -snf $$i.br_real $(ARCH)-linux$${i##$(GNU_TARGET_NAME)}.br_real; \
;; \
+ *ld) \
+ if [ ! -e $$i.br_real ] ; then \
+ mv $$i $$i.br_real; \
+ ln -sf toolchain-wrapper-linker $$i; \
+ ln -sf toolchain-wrapper-linker $(ARCH)-linux$${i##$(GNU_TARGET_NAME)}; \
+ ln -snf $$i.br_real $(ARCH)-linux$${i##$(GNU_TARGET_NAME)}.br_real; \
+ fi; \
+ ;; \
*) \
ln -snf $$i $(ARCH)-linux$${i##$(GNU_TARGET_NAME)}; \
;; \
diff --git a/toolchain/toolchain-external/pkg-toolchain-external.mk b/toolchain/toolchain-external/pkg-toolchain-external.mk
index 8b2c283..99eea68 100644
--- a/toolchain/toolchain-external/pkg-toolchain-external.mk
+++ b/toolchain/toolchain-external/pkg-toolchain-external.mk
@@ -90,10 +90,16 @@ endif
TOOLCHAIN_EXTERNAL_SUFFIX = \
$(if $(wildcard $(TOOLCHAIN_EXTERNAL_BIN)/*.br_real),.br_real)
+# Handle the case where there are bootlin toolchain's without ld wrappers which
+# would not have a .br_real defined.
+TOOLCHAIN_EXTERNAL_LD_SUFFIX = \
+ $(if $(wildcard $(TOOLCHAIN_EXTERNAL_BIN)/*ld.br_real),.br_real)
+
TOOLCHAIN_EXTERNAL_CROSS = $(TOOLCHAIN_EXTERNAL_BIN)/$(TOOLCHAIN_EXTERNAL_PREFIX)-
TOOLCHAIN_EXTERNAL_CC = $(TOOLCHAIN_EXTERNAL_CROSS)gcc$(TOOLCHAIN_EXTERNAL_SUFFIX)
TOOLCHAIN_EXTERNAL_CXX = $(TOOLCHAIN_EXTERNAL_CROSS)g++$(TOOLCHAIN_EXTERNAL_SUFFIX)
TOOLCHAIN_EXTERNAL_FC = $(TOOLCHAIN_EXTERNAL_CROSS)gfortran$(TOOLCHAIN_EXTERNAL_SUFFIX)
+TOOLCHAIN_EXTERNAL_LD = $(TOOLCHAIN_EXTERNAL_CROSS)ld$(TOOLCHAIN_EXTERNAL_LD_SUFFIX)
TOOLCHAIN_EXTERNAL_READELF = $(TOOLCHAIN_EXTERNAL_CROSS)readelf
# Normal handling of downloaded toolchain tarball extraction.
@@ -229,7 +235,8 @@ TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += -DBR_SOFTFLOAT=1
endif
TOOLCHAIN_EXTERNAL_TOOLCHAIN_WRAPPER_ARGS += \
- -DBR_CROSS_PATH_SUFFIX='"$(TOOLCHAIN_EXTERNAL_SUFFIX)"'
+ -DBR_CROSS_PATH_SUFFIX='"$(TOOLCHAIN_EXTERNAL_SUFFIX)"' \
+ -DBR_CROSS_PATH_LD_SUFFIX='"$(TOOLCHAIN_EXTERNAL_LD_SUFFIX)"' \
ifeq ($(filter $(HOST_DIR)/%,$(TOOLCHAIN_EXTERNAL_BIN)),)
# TOOLCHAIN_EXTERNAL_BIN points outside HOST_DIR => absolute path
@@ -274,6 +281,9 @@ define TOOLCHAIN_EXTERNAL_INSTALL_WRAPPER
ln -sf $$(echo $$i | sed 's%^$(HOST_DIR)%..%') .; \
fi \
;; \
+ *ld) \
+ ln -sf toolchain-wrapper-linker $$base; \
+ ;; \
*) \
ln -sf $$(echo $$i | sed 's%^$(HOST_DIR)%..%') .; \
;; \
diff --git a/toolchain/toolchain-wrapper-linker.c b/toolchain/toolchain-wrapper-linker.c
new file mode 100644
index 0000000..b587fea
--- /dev/null
+++ b/toolchain/toolchain-wrapper-linker.c
@@ -0,0 +1,248 @@
+/**
+ * Buildroot wrapper for toolchains. This simply executes the real toolchain
+ * with a number of arguments hardcoded, to ensure the toolchain uses the
+ * correct configuration.
+
+ * This file is based on the original wrapper code but updated for the linker.
+ *
+ * (C) 2011 Peter Korsgaard <jacmet@sunsite.dk>
+ * (C) 2011 Daniel Nystr?m <daniel.nystrom@timeterminal.se>
+ * (C) 2012 Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
+ * (C) 2013 Spenser Gilliland <spenser@gillilanding.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+#include <stdbool.h>
+
+static char path[PATH_MAX];
+
+/**
+ * GCC linker errors out with certain combinations of arguments (examples are
+ * static/shared/r/pie, so we have to ensure that we only pass the predefined
+ * one to the real compiler if the inverse option isn't in the argument list.
+ * This specifies the worst case number of extra arguments we might pass
+ * Currently, we may have:
+ */
+#define EXCLUSIVE_ARGS 0
+
+static char *predef_args[] = {
+ path
+};
+
+
+
+/* A {string,length} tuple, to avoid computing strlen() on constants.
+ * - str must be a \0-terminated string
+ * - len does not account for the terminating '\0'
+ */
+struct str_len_s {
+ const char *str;
+ size_t len;
+};
+
+/* Define a {string,length} tuple. Takes an unquoted constant string as
+ * parameter. sizeof() on a string literal includes the terminating \0,
+ * but we don't want to count it.
+ */
+#define STR_LEN(s) { #s, sizeof(#s)-1 }
+
+/* List of paths considered unsafe for cross-compilation.
+ *
+ * An unsafe path is one that points to a directory with libraries or
+ * headers for the build machine, which are not suitable for the target.
+ */
+static const struct str_len_s unsafe_paths[] = {
+ STR_LEN(/lib),
+ STR_LEN(/usr/include),
+ STR_LEN(/usr/lib),
+ STR_LEN(/usr/local/include),
+ STR_LEN(/usr/local/lib),
+ { NULL, 0 },
+};
+
+/* Unsafe options are options that specify a potentialy unsafe path,
+ * that will be checked by check_unsafe_path(), below.
+ */
+static const struct str_len_s unsafe_opts[] = {
+ STR_LEN(-I),
+ STR_LEN(-idirafter),
+ STR_LEN(-iquote),
+ STR_LEN(-isystem),
+ STR_LEN(-L),
+ { NULL, 0 },
+};
+
+/* Check if path is unsafe for cross-compilation. Unsafe paths are those
+ * pointing to the standard native include or library paths.
+ *
+ * We print the arguments leading to the failure. For some options, gcc
+ * accepts the path to be concatenated to the argument (e.g. -I/foo/bar)
+ * or separated (e.g. -I /foo/bar). In the first case, we need only print
+ * the argument as it already contains the path (arg_has_path), while in
+ * the second case we need to print both (!arg_has_path).
+ *
+ * If paranoid, exit in error instead of just printing a warning.
+ */
+static void check_unsafe_path(const char *arg,
+ const char *path,
+ int paranoid,
+ int arg_has_path)
+{
+ const struct str_len_s *p;
+
+ for (p=unsafe_paths; p->str; p++) {
+ if (strncmp(path, p->str, p->len))
+ continue;
+ fprintf(stderr,
+ "%s: %s: unsafe header/library path used in cross-compilation: '%s%s%s'\n",
+ program_invocation_short_name,
+ paranoid ? "ERROR" : "WARNING",
+ arg,
+ arg_has_path ? "" : "' '", /* close single-quote, space, open single-quote */
+ arg_has_path ? "" : path); /* so that arg and path are properly quoted. */
+ if (paranoid)
+ exit(1);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ char **args, **cur, **exec_args;
+ char *relbasedir, *absbasedir;
+ char *progpath = argv[0];
+ char *basename;
+ char *env_debug;
+ char *paranoid_wrapper;
+ int paranoid;
+ int ret, i, count = 0, debug;
+
+ /* Calculate the relative paths */
+ basename = strrchr(progpath, '/');
+ if (basename) {
+ *basename = '\0';
+ basename++;
+ relbasedir = malloc(strlen(progpath) + 7);
+ if (relbasedir == NULL) {
+ perror(__FILE__ ": malloc");
+ return 2;
+ }
+ sprintf(relbasedir, "%s/..", argv[0]);
+ absbasedir = realpath(relbasedir, NULL);
+ } else {
+ basename = progpath;
+ absbasedir = malloc(PATH_MAX + 1);
+ ret = readlink("/proc/self/exe", absbasedir, PATH_MAX);
+ if (ret < 0) {
+ perror(__FILE__ ": readlink");
+ return 2;
+ }
+ absbasedir[ret] = '\0';
+ for (i = ret; i > 0; i--) {
+ if (absbasedir[i] == '/') {
+ absbasedir[i] = '\0';
+ if (++count == 2)
+ break;
+ }
+ }
+ }
+ if (absbasedir == NULL) {
+ perror(__FILE__ ": realpath");
+ return 2;
+ }
+
+ /* Fill in the relative paths */
+#ifdef BR_CROSS_PATH_REL
+ ret = snprintf(path, sizeof(path), "%s/" BR_CROSS_PATH_REL "/%s" BR_CROSS_PATH_LD_SUFFIX, absbasedir, basename);
+#elif defined(BR_CROSS_PATH_ABS)
+ ret = snprintf(path, sizeof(path), BR_CROSS_PATH_ABS "/%s" BR_CROSS_PATH_LD_SUFFIX, basename);
+#else
+ ret = snprintf(path, sizeof(path), "%s/bin/%s" BR_CROSS_PATH_LD_SUFFIX, absbasedir, basename);
+#endif
+ if (ret >= sizeof(path)) {
+ perror(__FILE__ ": overflow");
+ return 3;
+ }
+
+ cur = args = malloc(sizeof(predef_args) +
+ (sizeof(char *) * (argc + EXCLUSIVE_ARGS)));
+ if (args == NULL) {
+ perror(__FILE__ ": malloc");
+ return 2;
+ }
+
+ /* start with predefined args */
+ memcpy(cur, predef_args, sizeof(predef_args));
+ cur += sizeof(predef_args) / sizeof(predef_args[0]);
+
+ paranoid_wrapper = getenv("BR_COMPILER_PARANOID_UNSAFE_PATH");
+ if (paranoid_wrapper && strlen(paranoid_wrapper) > 0)
+ paranoid = 1;
+ else
+ paranoid = 0;
+
+ /* Check for unsafe library and header paths */
+ for (i = 1; i < argc; i++) {
+ const struct str_len_s *opt;
+ for (opt=unsafe_opts; opt->str; opt++ ) {
+ /* Skip any non-unsafe option. */
+ if (strncmp(argv[i], opt->str, opt->len))
+ continue;
+
+ /* Handle both cases:
+ * - path is a separate argument,
+ * - path is concatenated with option.
+ */
+ if (argv[i][opt->len] == '\0') {
+ i++;
+ if (i == argc)
+ break;
+ check_unsafe_path(argv[i-1], argv[i], paranoid, 0);
+ } else
+ check_unsafe_path(argv[i], argv[i] + opt->len, paranoid, 1);
+ }
+ }
+
+ /* append forward args */
+ memcpy(cur, &argv[1], sizeof(char *) * (argc - 1));
+ cur += argc - 1;
+
+ /* finish with NULL termination */
+ *cur = NULL;
+
+ exec_args = args;
+
+ /* Debug the wrapper to see actual arguments passed to
+ * the compiler:
+ * unset, empty, or 0: do not trace
+ * set to 1 : trace all arguments on a single line
+ * set to 2 : trace one argument per line
+ */
+ if ((env_debug = getenv("BR2_DEBUG_WRAPPER"))) {
+ debug = atoi(env_debug);
+ if (debug > 0) {
+ fprintf(stderr, "Toolchain wrapper executing:");
+ for (i = 0; exec_args[i]; i++)
+ fprintf(stderr, "%s'%s'",
+ (debug == 2) ? "\n " : " ", exec_args[i]);
+ fprintf(stderr, "\n");
+ }
+ }
+
+ if (execv(exec_args[0], exec_args))
+ perror(path);
+
+ free(args);
+
+ return 2;
+}
diff --git a/toolchain/toolchain-wrapper.mk b/toolchain/toolchain-wrapper.mk
index b8074ef..3a4cbcd 100644
--- a/toolchain/toolchain-wrapper.mk
+++ b/toolchain/toolchain-wrapper.mk
@@ -50,9 +50,15 @@ define TOOLCHAIN_WRAPPER_BUILD
-s -Wl,--hash-style=$(TOOLCHAIN_WRAPPER_HASH_STYLE) \
toolchain/toolchain-wrapper.c \
-o $(@D)/toolchain-wrapper
+ $(HOSTCC) $(HOST_CFLAGS) $(TOOLCHAIN_WRAPPER_ARGS) \
+ -s -Wl,--hash-style=$(TOOLCHAIN_WRAPPER_HASH_STYLE) \
+ toolchain/toolchain-wrapper-linker.c \
+ -o $(@D)/toolchain-wrapper-linker
endef
define TOOLCHAIN_WRAPPER_INSTALL
$(INSTALL) -D -m 0755 $(@D)/toolchain-wrapper \
$(HOST_DIR)/bin/toolchain-wrapper
+ $(INSTALL) -D -m 0755 $(@D)/toolchain-wrapper-linker \
+ $(HOST_DIR)/bin/toolchain-wrapper-linker
endef
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Buildroot] [PATCH v2 2/5] toolchain/toolchain-wrapper: add BR2_RELRO_FULL support
2018-08-30 3:34 [Buildroot] [PATCH v2 0/5] Hardening Wrapper Updates and Test Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper Matt Weber
@ 2018-08-30 3:34 ` Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 3/5] toolchain/toolchain-wrapper: add BR2_SSP_* support Matt Weber
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Matt Weber @ 2018-08-30 3:34 UTC (permalink / raw)
To: buildroot
Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
---
Changes
v1 -> v2
- Reworked handling of pie/pic/shared to replace each time they
occur with a dummy string and then insert the right combination
when rebuilding the exec string.
- Fixed mix of tabs and spaces
- Swapped order of shared and pie. Coded it backwards.
---
package/Makefile.in | 5 +++--
toolchain/toolchain-wrapper-linker.c | 27 +++++++++++++++++++++-
toolchain/toolchain-wrapper.c | 43 +++++++++++++++++++++++++++++++++++-
toolchain/toolchain-wrapper.mk | 4 ++++
4 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/package/Makefile.in b/package/Makefile.in
index 14b3bbd..2e885bf 100644
--- a/package/Makefile.in
+++ b/package/Makefile.in
@@ -158,8 +158,9 @@ ifeq ($(BR2_RELRO_PARTIAL),y)
TARGET_HARDENED += $(TARGET_CFLAGS_RELRO)
TARGET_LDFLAGS += $(TARGET_CFLAGS_RELRO)
else ifeq ($(BR2_RELRO_FULL),y)
-TARGET_HARDENED += -fPIE $(TARGET_CFLAGS_RELRO_FULL)
-TARGET_LDFLAGS += -pie $(TARGET_CFLAGS_RELRO_FULL)
+TARGET_HARDENED += $(TARGET_CFLAGS_RELRO_FULL)
+# -DBR_SET_PIE is used by the GCC wrapper to tell when linking
+TARGET_LDFLAGS += $(TARGET_CFLAGS_RELRO_FULL) -DBR_SET_PIE
endif
ifeq ($(BR2_FORTIFY_SOURCE_1),y)
diff --git a/toolchain/toolchain-wrapper-linker.c b/toolchain/toolchain-wrapper-linker.c
index b587fea..32e8156 100644
--- a/toolchain/toolchain-wrapper-linker.c
+++ b/toolchain/toolchain-wrapper-linker.c
@@ -33,8 +33,10 @@ static char path[PATH_MAX];
* one to the real compiler if the inverse option isn't in the argument list.
* This specifies the worst case number of extra arguments we might pass
* Currently, we may have:
+ * -pie
+ * -shared
*/
-#define EXCLUSIVE_ARGS 0
+#define EXCLUSIVE_ARGS 2
static char *predef_args[] = {
path
@@ -126,6 +128,7 @@ int main(int argc, char **argv)
char *paranoid_wrapper;
int paranoid;
int ret, i, count = 0, debug;
+ unsigned int found_shared = 0;
/* Calculate the relative paths */
basename = strrchr(progpath, '/');
@@ -185,6 +188,28 @@ int main(int argc, char **argv)
memcpy(cur, predef_args, sizeof(predef_args));
cur += sizeof(predef_args) / sizeof(predef_args[0]);
+#ifdef BR2_RELRO_FULL
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-static") ||
+ !strcmp(argv[i], "-r"))
+ break;
+
+ if( !strcmp(argv[i], "-shared") ) {
+ /* Setting the value to something so that the compiler
+ doesn't error on a empty '' when -share is removed */
+ argv[i] = "-DBR_REMOVED_-shared";
+ found_shared = 1;
+ }
+ }
+
+ if (i == argc) {
+ *cur++ = "-pie";
+
+ if( found_shared )
+ *cur++ = "-shared";
+ }
+#endif
+
paranoid_wrapper = getenv("BR_COMPILER_PARANOID_UNSAFE_PATH");
if (paranoid_wrapper && strlen(paranoid_wrapper) > 0)
paranoid = 1;
diff --git a/toolchain/toolchain-wrapper.c b/toolchain/toolchain-wrapper.c
index c5eb813..4649091 100644
--- a/toolchain/toolchain-wrapper.c
+++ b/toolchain/toolchain-wrapper.c
@@ -49,8 +49,11 @@ static char _date_[sizeof("-D__DATE__=\"MMM DD YYYY\"")];
* -D__TIME__=
* -D__DATE__=
* -Wno-builtin-macro-redefined
+ * -fPIE
+ * -shared (if linking)
+ * -pie (if linking)
*/
-#define EXCLUSIVE_ARGS 6
+#define EXCLUSIVE_ARGS 9
static char *predef_args[] = {
#ifdef BR_CCACHE
@@ -237,6 +240,7 @@ int main(int argc, char **argv)
char *paranoid_wrapper;
int paranoid;
int ret, i, count = 0, debug;
+ unsigned int gcc_using_link_flags = 0, found_shared = 0;
/* Calculate the relative paths */
basename = strrchr(progpath, '/');
@@ -363,6 +367,43 @@ int main(int argc, char **argv)
*cur++ = "-Wno-builtin-macro-redefined";
}
+#ifdef BR2_RELRO_FULL
+ /* Must handle combinations of compiler/link options */
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-r") ||
+ !strcmp(argv[i], "-static") ||
+ !strcmp(argv[i], "-fno-pic"))
+ break;
+
+ /* Setting the value to something for each of these so
+ that the compiler doesn't error on a empty '' */
+ if (!strcmp(argv[i], "-fpie"))
+ argv[i] = "-DBR_REMOVED_-fpie";
+ if (!strcmp(argv[i], "-fPIE"))
+ argv[i] = "-DBR_REMOVED_-fPIE";
+ if (!strcmp(argv[i], "-fPIC"))
+ argv[i] = "-DBR_REMOVED_-fPIC";
+ if( !strcmp(argv[i], "-shared") ) {
+ argv[i] = "-DBR_REMOVED_-shared";
+ found_shared = 1;
+ }
+
+ /* Find the define identifing LDFLAGS were provided */
+ if( !strcmp(argv[i], "-DBR_SET_PIE") )
+ gcc_using_link_flags = 1;
+ }
+
+ if (i == argc) {
+ *cur++ = "-fPIE";
+
+ /* Handle case where gcc is linking with LDFlags */
+ if( gcc_using_link_flags )
+ *cur++ = "-pie";
+ if( found_shared )
+ *cur++ = "-shared";
+ }
+#endif
+
paranoid_wrapper = getenv("BR_COMPILER_PARANOID_UNSAFE_PATH");
if (paranoid_wrapper && strlen(paranoid_wrapper) > 0)
paranoid = 1;
diff --git a/toolchain/toolchain-wrapper.mk b/toolchain/toolchain-wrapper.mk
index 3a4cbcd..b0e44b3 100644
--- a/toolchain/toolchain-wrapper.mk
+++ b/toolchain/toolchain-wrapper.mk
@@ -45,6 +45,10 @@ ifeq ($(BR2_CCACHE_USE_BASEDIR),y)
TOOLCHAIN_WRAPPER_ARGS += -DBR_CCACHE_BASEDIR='"$(BASE_DIR)"'
endif
+ifeq ($(BR2_RELRO_FULL),y)
+TOOLCHAIN_WRAPPER_ARGS += -DBR2_RELRO_FULL
+endif
+
define TOOLCHAIN_WRAPPER_BUILD
$(HOSTCC) $(HOST_CFLAGS) $(TOOLCHAIN_WRAPPER_ARGS) \
-s -Wl,--hash-style=$(TOOLCHAIN_WRAPPER_HASH_STYLE) \
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Buildroot] [PATCH v2 3/5] toolchain/toolchain-wrapper: add BR2_SSP_* support
2018-08-30 3:34 [Buildroot] [PATCH v2 0/5] Hardening Wrapper Updates and Test Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 2/5] toolchain/toolchain-wrapper: add BR2_RELRO_FULL support Matt Weber
@ 2018-08-30 3:34 ` Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 4/5] toolchain/toolchain-wrapper: add BR2_FORTIFY_SOURCE_* support Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 5/5] support/testing/tests/core: SSP & hardening flags Matt Weber
4 siblings, 0 replies; 8+ messages in thread
From: Matt Weber @ 2018-08-30 3:34 UTC (permalink / raw)
To: buildroot
Migrate the stack protection flag management into the wrapper.
Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
---
package/Makefile.in | 8 --------
toolchain/toolchain-wrapper.c | 9 +++++++++
toolchain/toolchain-wrapper.mk | 8 ++++++++
3 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/package/Makefile.in b/package/Makefile.in
index 2e885bf..ed6fd0d 100644
--- a/package/Makefile.in
+++ b/package/Makefile.in
@@ -146,14 +146,6 @@ TARGET_CFLAGS_RELRO_FULL = -Wl,-z,now $(TARGET_CFLAGS_RELRO)
TARGET_LDFLAGS = $(call qstrip,$(BR2_TARGET_LDFLAGS))
-ifeq ($(BR2_SSP_REGULAR),y)
-TARGET_HARDENED += -fstack-protector
-else ifeq ($(BR2_SSP_STRONG),y)
-TARGET_HARDENED += -fstack-protector-strong
-else ifeq ($(BR2_SSP_ALL),y)
-TARGET_HARDENED += -fstack-protector-all
-endif
-
ifeq ($(BR2_RELRO_PARTIAL),y)
TARGET_HARDENED += $(TARGET_CFLAGS_RELRO)
TARGET_LDFLAGS += $(TARGET_CFLAGS_RELRO)
diff --git a/toolchain/toolchain-wrapper.c b/toolchain/toolchain-wrapper.c
index 4649091..6c5ea1a 100644
--- a/toolchain/toolchain-wrapper.c
+++ b/toolchain/toolchain-wrapper.c
@@ -97,6 +97,15 @@ static char *predef_args[] = {
#if defined(BR_MIPS_TARGET_BIG_ENDIAN) || defined(BR_ARC_TARGET_BIG_ENDIAN)
"-EB",
#endif
+#ifdef BR_SSP_REGULAR
+ "-fstack-protector",
+#endif
+#ifdef BR_SSP_STRONG
+ "-fstack-protector-strong",
+#endif
+#ifdef BR_SSP_ALL
+ "-fstack-protector-all",
+#endif
#ifdef BR_ADDITIONAL_CFLAGS
BR_ADDITIONAL_CFLAGS
#endif
diff --git a/toolchain/toolchain-wrapper.mk b/toolchain/toolchain-wrapper.mk
index b0e44b3..15f1a74 100644
--- a/toolchain/toolchain-wrapper.mk
+++ b/toolchain/toolchain-wrapper.mk
@@ -49,6 +49,14 @@ ifeq ($(BR2_RELRO_FULL),y)
TOOLCHAIN_WRAPPER_ARGS += -DBR2_RELRO_FULL
endif
+ifeq ($(BR2_SSP_REGULAR),y)
+TOOLCHAIN_WRAPPER_ARGS += -DBR_SSP_REGULAR
+else ifeq ($(BR2_SSP_STRONG),y)
+TOOLCHAIN_WRAPPER_ARGS += -DBR_SSP_STRONG
+else ifeq ($(BR2_SSP_ALL),y)
+TOOLCHAIN_WRAPPER_ARGS += -DBR_SSP_ALL
+endif
+
define TOOLCHAIN_WRAPPER_BUILD
$(HOSTCC) $(HOST_CFLAGS) $(TOOLCHAIN_WRAPPER_ARGS) \
-s -Wl,--hash-style=$(TOOLCHAIN_WRAPPER_HASH_STYLE) \
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Buildroot] [PATCH v2 4/5] toolchain/toolchain-wrapper: add BR2_FORTIFY_SOURCE_* support
2018-08-30 3:34 [Buildroot] [PATCH v2 0/5] Hardening Wrapper Updates and Test Matt Weber
` (2 preceding siblings ...)
2018-08-30 3:34 ` [Buildroot] [PATCH v2 3/5] toolchain/toolchain-wrapper: add BR2_SSP_* support Matt Weber
@ 2018-08-30 3:34 ` Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 5/5] support/testing/tests/core: SSP & hardening flags Matt Weber
4 siblings, 0 replies; 8+ messages in thread
From: Matt Weber @ 2018-08-30 3:34 UTC (permalink / raw)
To: buildroot
Migrate the fortify flag management into the wrapper.
Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
---
package/Makefile.in | 6 ------
toolchain/toolchain-wrapper.c | 6 ++++++
toolchain/toolchain-wrapper.mk | 6 ++++++
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/package/Makefile.in b/package/Makefile.in
index ed6fd0d..d1f9789 100644
--- a/package/Makefile.in
+++ b/package/Makefile.in
@@ -155,12 +155,6 @@ TARGET_HARDENED += $(TARGET_CFLAGS_RELRO_FULL)
TARGET_LDFLAGS += $(TARGET_CFLAGS_RELRO_FULL) -DBR_SET_PIE
endif
-ifeq ($(BR2_FORTIFY_SOURCE_1),y)
-TARGET_HARDENED += -D_FORTIFY_SOURCE=1
-else ifeq ($(BR2_FORTIFY_SOURCE_2),y)
-TARGET_HARDENED += -D_FORTIFY_SOURCE=2
-endif
-
TARGET_CPPFLAGS += -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
TARGET_CFLAGS = $(TARGET_CPPFLAGS) $(TARGET_ABI) $(TARGET_OPTIMIZATION) $(TARGET_DEBUGGING) $(TARGET_HARDENED)
TARGET_CXXFLAGS = $(TARGET_CFLAGS)
diff --git a/toolchain/toolchain-wrapper.c b/toolchain/toolchain-wrapper.c
index 6c5ea1a..a2d5f1d 100644
--- a/toolchain/toolchain-wrapper.c
+++ b/toolchain/toolchain-wrapper.c
@@ -106,6 +106,12 @@ static char *predef_args[] = {
#ifdef BR_SSP_ALL
"-fstack-protector-all",
#endif
+#ifdef BR_FORTIFY_SOURCE_1
+ "-D_FORTIFY_SOURCE=1",
+#endif
+#ifdef BR_FORTIFY_SOURCE_2
+ "-D_FORTIFY_SOURCE=2",
+#endif
#ifdef BR_ADDITIONAL_CFLAGS
BR_ADDITIONAL_CFLAGS
#endif
diff --git a/toolchain/toolchain-wrapper.mk b/toolchain/toolchain-wrapper.mk
index 15f1a74..8b8db8b 100644
--- a/toolchain/toolchain-wrapper.mk
+++ b/toolchain/toolchain-wrapper.mk
@@ -57,6 +57,12 @@ else ifeq ($(BR2_SSP_ALL),y)
TOOLCHAIN_WRAPPER_ARGS += -DBR_SSP_ALL
endif
+ifeq ($(BR2_FORTIFY_SOURCE_1),y)
+TOOLCHAIN_WRAPPER_ARGS += -DBR_FORTIFY_SOURCE_1
+else ifeq ($(BR2_FORTIFY_SOURCE_2),y)
+TOOLCHAIN_WRAPPER_ARGS += -DBR_FORTIFY_SOURCE_2
+endif
+
define TOOLCHAIN_WRAPPER_BUILD
$(HOSTCC) $(HOST_CFLAGS) $(TOOLCHAIN_WRAPPER_ARGS) \
-s -Wl,--hash-style=$(TOOLCHAIN_WRAPPER_HASH_STYLE) \
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Buildroot] [PATCH v2 5/5] support/testing/tests/core: SSP & hardening flags
2018-08-30 3:34 [Buildroot] [PATCH v2 0/5] Hardening Wrapper Updates and Test Matt Weber
` (3 preceding siblings ...)
2018-08-30 3:34 ` [Buildroot] [PATCH v2 4/5] toolchain/toolchain-wrapper: add BR2_FORTIFY_SOURCE_* support Matt Weber
@ 2018-08-30 3:34 ` Matt Weber
4 siblings, 0 replies; 8+ messages in thread
From: Matt Weber @ 2018-08-30 3:34 UTC (permalink / raw)
To: buildroot
Catch the commonly used options of SSP, Relro, and fortify.
Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
---
Changes
Original v4 -> v1 of link wrapper patchset
- Added back in busybox test case
v3 -> v4
- Removed commented out lines I missed when I removed busybox
- Removed duplicate fortify assertion test
v2 -> v3
[Matt
- Removed the busybox target as without the link time
wrapper/specfile being merged the build will fail.
Link time conflict between use of 'r' and pie.
[Thomas
- Add clarificaion of what checksec can test
- Reworked using inheritance
- Relocated json load (removed duplication)
v1 -> v2
[Ricardo
- Fix flake8 warnings
- Added missing busyfox pie assertions
- Updated the yml to include new test cases
---
.gitlab-ci.yml | 6 ++
support/testing/tests/core/test_hardening.py | 110 +++++++++++++++++++++++++++
2 files changed, 116 insertions(+)
create mode 100644 support/testing/tests/core/test_hardening.py
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3fc9b06..c271c05 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -261,6 +261,12 @@ zynqmp_zcu106_defconfig: *defconfig
tests.boot.test_atf.TestATFAllwinner: *runtime_test
tests.boot.test_atf.TestATFMarvell: *runtime_test
tests.boot.test_atf.TestATFVexpress: *runtime_test
+tests.core.test_hardening.TestFortifyConserv: *runtime_test
+tests.core.test_hardening.TestFortifyNone: *runtime_test
+tests.core.test_hardening.TestRelro: *runtime_test
+tests.core.test_hardening.TestRelroPartial: *runtime_test
+tests.core.test_hardening.TestSspNone: *runtime_test
+tests.core.test_hardening.TestSspStrong: *runtime_test
tests.core.test_post_scripts.TestPostScripts: *runtime_test
tests.core.test_rootfs_overlay.TestRootfsOverlay: *runtime_test
tests.core.test_timezone.TestGlibcAllTimezone: *runtime_test
diff --git a/support/testing/tests/core/test_hardening.py b/support/testing/tests/core/test_hardening.py
new file mode 100644
index 0000000..9f26962
--- /dev/null
+++ b/support/testing/tests/core/test_hardening.py
@@ -0,0 +1,110 @@
+import os
+import subprocess
+import json
+
+import infra.basetest
+
+
+class TestHardeningBase(infra.basetest.BRTest):
+ config = \
+ """
+ BR2_powerpc64=y
+ BR2_powerpc_e5500=y
+ BR2_TOOLCHAIN_EXTERNAL=y
+ BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y
+ BR2_TOOLCHAIN_EXTERNAL_URL="https://toolchains.bootlin.com/downloads/releases/toolchains/powerpc64-e5500/tarballs/powerpc64-e5500--glibc--stable-2018.02-2.tar.bz2"
+ BR2_TOOLCHAIN_EXTERNAL_GCC_6=y
+ BR2_TOOLCHAIN_EXTERNAL_HEADERS_4_1=y
+ BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC=y
+ BR2_TOOLCHAIN_EXTERNAL_CXX=y
+ BR2_PACKAGE_LIGHTTPD=y
+ BR2_PACKAGE_HOST_CHECKSEC=y
+ # BR2_TARGET_ROOTFS_TAR is not set
+ """
+
+ checksec_files = ["usr/sbin/lighttpd","bin/busybox"]
+
+ def checksec_run(self, target_file):
+ filepath = os.path.join(self.builddir, "target", target_file)
+ cmd = ["host/bin/checksec", "--output", "json", "--file", filepath]
+ # Checksec is being used for elf file analysis only. There are no
+ # assumptions of target/run-time checks as part of this testing.
+ ret = subprocess.check_output(cmd,
+ stderr=open(os.devnull, "w"),
+ cwd=self.builddir,
+ env={"LANG": "C"})
+ return json.loads(ret)
+
+
+class TestRelro(TestHardeningBase):
+ config = TestHardeningBase.config + \
+ """
+ BR2_RELRO_FULL=y
+ """
+
+ def test_run(self):
+ for f in self.checksec_files:
+ out = self.checksec_run(f)
+ self.assertEqual(out["file"]["relro"], "full")
+ self.assertEqual(out["file"]["pie"], "yes")
+
+
+class TestRelroPartial(TestHardeningBase):
+ config = TestHardeningBase.config + \
+ """
+ BR2_RELRO_PARTIAL=y
+ """
+
+ def test_run(self):
+ for f in self.checksec_files:
+ out = self.checksec_run(f)
+ self.assertEqual(out["file"]["relro"], "partial")
+ self.assertEqual(out["file"]["pie"], "no")
+
+
+class TestSspNone(TestHardeningBase):
+ config = TestHardeningBase.config + \
+ """
+ BR2_SSP_NONE=y
+ """
+
+ def test_run(self):
+ for f in self.checksec_files:
+ out = self.checksec_run(f)
+ self.assertEqual(out["file"]["canary"], "no")
+
+
+class TestSspStrong(TestHardeningBase):
+ config = TestHardeningBase.config + \
+ """
+ BR2_SSP_STRONG=y
+ """
+
+ def test_run(self):
+ for f in self.checksec_files:
+ out = self.checksec_run(f)
+ self.assertEqual(out["file"]["canary"], "yes")
+
+
+class TestFortifyNone(TestHardeningBase):
+ config = TestHardeningBase.config + \
+ """
+ BR2_FORTIFY_SOURCE_NONE=y
+ """
+
+ def test_run(self):
+ for f in self.checksec_files:
+ out = self.checksec_run(f)
+ self.assertEqual(out["file"]["fortified"], "0")
+
+
+class TestFortifyConserv(TestHardeningBase):
+ config = TestHardeningBase.config + \
+ """
+ BR2_FORTIFY_SOURCE_1=y
+ """
+
+ def test_run(self):
+ for f in self.checksec_files:
+ out = self.checksec_run(f)
+ self.assertNotEqual(out["file"]["fortified"], "0")
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper
2018-08-30 3:34 ` [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper Matt Weber
@ 2018-08-30 7:53 ` Thomas Petazzoni
2018-08-30 12:48 ` Matthew Weber
0 siblings, 1 reply; 8+ messages in thread
From: Thomas Petazzoni @ 2018-08-30 7:53 UTC (permalink / raw)
To: buildroot
Hello Matt,
On Wed, 29 Aug 2018 22:34:41 -0500, Matt Weber wrote:
> - Updates symlink creation int/ext toolchain
> - Adds new source file for link wrapper with build/install
>
> Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
I think this commit log should contain a detailed explanation of why
wrapping the linker is necessary. Could you provide an example of a
package that absolutely needs the linker to be wrapped ? I'd like to do
a bit of testing, because I'm still not entirely convinced that we want
to wrap the linker. Perhaps we need to do this, but I'd like to spend a
bit of time looking at a specific example of a package that makes this
necessary. Could you provide such an example ?
Thanks a lot!
Thomas
--
Thomas Petazzoni, CTO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper
2018-08-30 7:53 ` Thomas Petazzoni
@ 2018-08-30 12:48 ` Matthew Weber
0 siblings, 0 replies; 8+ messages in thread
From: Matthew Weber @ 2018-08-30 12:48 UTC (permalink / raw)
To: buildroot
Thomas,
On Thu, Aug 30, 2018 at 2:54 AM Thomas Petazzoni
<thomas.petazzoni@bootlin.com> wrote:
>
> Hello Matt,
>
> On Wed, 29 Aug 2018 22:34:41 -0500, Matt Weber wrote:
> > - Updates symlink creation int/ext toolchain
> > - Adds new source file for link wrapper with build/install
> >
> > Signed-off-by: Matthew Weber <matthew.weber@rockwellcollins.com>
>
> I think this commit log should contain a detailed explanation of why
> wrapping the linker is necessary. Could you provide an example of a
> package that absolutely needs the linker to be wrapped ? I'd like to do
> a bit of testing, because I'm still not entirely convinced that we want
> to wrap the linker. Perhaps we need to do this, but I'd like to spend a
> bit of time looking at a specific example of a package that makes this
> necessary. Could you provide such an example ?
>
Definitely. I can put together a few scenarios.
Right now the v2 series has an issue found by my night run of tests
and I'll have to respin. I'll include something in the v3 series.
All, if anyone build tests this, the v2 change to preserve -fPIC has
broken busybox individual binaries mode.
Matt
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2018-08-30 12:48 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-08-30 3:34 [Buildroot] [PATCH v2 0/5] Hardening Wrapper Updates and Test Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 1/5] toolchain/toolchain-wrapper: add link wrapper Matt Weber
2018-08-30 7:53 ` Thomas Petazzoni
2018-08-30 12:48 ` Matthew Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 2/5] toolchain/toolchain-wrapper: add BR2_RELRO_FULL support Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 3/5] toolchain/toolchain-wrapper: add BR2_SSP_* support Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 4/5] toolchain/toolchain-wrapper: add BR2_FORTIFY_SOURCE_* support Matt Weber
2018-08-30 3:34 ` [Buildroot] [PATCH v2 5/5] support/testing/tests/core: SSP & hardening flags Matt Weber
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox