[Buildroot] [PATCH v7 1/4] toolchain/toolchain-wrapper: add BR2_RELRO_
Peter Korsgaard
peter at korsgaard.com
Sat Oct 20 10:49:58 UTC 2018
>>>>> "Matt" == Matt Weber <matthew.weber at rockwellcollins.com> writes:
> The RELRO/PIE flags are currently passed via CFLAGS/LDFLAGS and this patch
> proposes moving them to the toolchain wrapper.
> (1) The flags should _always_ be passed, without leaving the possibility
> for any package to ignore them. I.e, when BR2_RELRO_FULL=y is used
> in a build, all executables should be built PIE. Passing those
> options through the wrapper ensures they are used during the build
> of all packages.
> (2) Some options are incompatible with -fPIE. For example, when
> building object files for a shared libraries, -fPIC is used, and
> -fPIE shouldn't be used in combination with -fPIE. Similarly, -r
> or -static are directly incompatible as they are different link
> time behaviors then the intent of PIE. Passing those options
> through the wrapper allows to add some "smart" logic to only pass
> -fPIE/-pie when relevant.
> (3) Some toolchain, kernel and bootloader packages may want to
> explicitly disable PIE in a build where the rest of the userspace
> has intentionally enabled it. The wrapper provides an option
> to key on the -fno-pie/-no-pie and bypass the appending of RELRO
> flags.
> The current Kernel and U-boot source trees include this option.
> https://github.com/torvalds/linux/commit/8438ee76b004ef66d125ade64c91fc128047d244
> https://github.com/u-boot/u-boot/commit/6ace36e19a8cfdd16ce7c02625edf36864897bf5
> If using PIE with a older Kernel and/or U-boot version, a backport of these
> changes might be required. However this patchset also uses the
> __KERNEL__ and __UBOOT__ defines as a way to disable PIE.
> NOTE: The current implementation via CFLAGS/LDFLAGS is has caused some
> build time failures as the conditional logic doesn't yet exist in
> Buildroot.
> https://bugs.busybox.net/show_bug.cgi?id=11206
> https://bugs.busybox.net/show_bug.cgi?id=11321
> Good summary of the most common build failures related to
> enabling pie. https://wiki.ubuntu.com/SecurityTeam/PIE
> Signed-off-by: Matthew Weber <matthew.weber at rockwellcollins.com>
> ---
> Changes
> v6 -> v7
> - Fixed rebase error with a stray endif
> v5 -> v6
> [Thomas
> - Fixed commit logs description to describe the change
> - Moved relro partial options to wrapper and updated this commit
> title to make the patch generically capture the move of _RELRO_
> - Added comment to wrapper and commit about use of no-pie
> - Added a comment in the wrapper and above to cover conversation on
> Linux kernel and uboot no-pie fix-ups. Plus added a condition
> checking for the __KERNEL__ and __UBOOT__ defines
> - Add comment that -fPIE and -pie can interchangeably be used during
> link/compile and are correctly ignored when not used.
> [Arnout
> - Collapsed the -pie conditional in the wrapper to be within the
> check for use of -fPIE. Also resolves missing -Wl,-r in the -fPIE loop
> - Removed specfile and consolidated into just the gcc frontend wrapper
> v4 -> v5
> - Found -r can also be -wl,r. Wrapper has been updated to cover
> that case.
> v3 -> v4
> [Matt W
> - Added no-pie/pic options to allow per package tweaking of
> wrapper setting the option. This lines up with other distros
> [Arnout
> - After realizing that a LD invocation doesn't use the specfile,
> I agree with Arnout and have tested the solution can completely
> occur within the compiler wrapper. This version updates to just
> have modifications in the wrapper.
> v2 -> v3
> - Fell back on a linker approach using a spec file and kept compiler
> flag tweaks in the wrapper
> 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. Originally coded it backwards.
> ---
> package/Makefile.in | 11 ------
> toolchain/toolchain-wrapper.c | 82 ++++++++++++++++++++++++++++++++++++++++--
> toolchain/toolchain-wrapper.mk | 6 ++++
> 3 files changed, 86 insertions(+), 13 deletions(-)
> diff --git a/package/Makefile.in b/package/Makefile.in
> index abfdb81..cd21482 100644
> --- a/package/Makefile.in
> +++ b/package/Makefile.in
> @@ -141,9 +141,6 @@ ifeq ($(BR2_DEBUG_3),y)
> TARGET_DEBUGGING = -g3
> endif
> -TARGET_CFLAGS_RELRO = -Wl,-z,relro
> -TARGET_CFLAGS_RELRO_FULL = -Wl,-z,now $(TARGET_CFLAGS_RELRO)
> -
> TARGET_LDFLAGS = $(call qstrip,$(BR2_TARGET_LDFLAGS))
> ifeq ($(BR2_SSP_REGULAR),y)
> @@ -154,14 +151,6 @@ 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)
> -else ifeq ($(BR2_RELRO_FULL),y)
> -TARGET_HARDENED += -fPIE $(TARGET_CFLAGS_RELRO_FULL)
> -TARGET_LDFLAGS += -pie $(TARGET_CFLAGS_RELRO_FULL)
> -endif
> -
> ifeq ($(BR2_FORTIFY_SOURCE_1),y)
> TARGET_HARDENED += -D_FORTIFY_SOURCE=1
> else ifeq ($(BR2_FORTIFY_SOURCE_2),y)
> diff --git a/toolchain/toolchain-wrapper.c b/toolchain/toolchain-wrapper.c
> index c5eb813..153ba87 100644
> --- a/toolchain/toolchain-wrapper.c
> +++ b/toolchain/toolchain-wrapper.c
> @@ -49,8 +49,12 @@ static char _date_[sizeof("-D__DATE__=\"MMM DD YYYY\"")];
> * -D__TIME__=
> * -D__DATE__=
> * -Wno-builtin-macro-redefined
> + * -Wl,-z,now
> + * -Wl,-z,relro
> + * -fPIE
> + * -pie
> */
> -#define EXCLUSIVE_ARGS 6
> +#define EXCLUSIVE_ARGS 10
> static char *predef_args[] = {
> #ifdef BR_CCACHE
> @@ -236,7 +240,8 @@ int main(int argc, char **argv)
> char *env_debug;
> char *paranoid_wrapper;
> int paranoid;
> - int ret, i, count = 0, debug;
> + int ret, i, j, count = 0, debug;
> + unsigned int found_shared = 0;
There is not really any specific reason why found_shared is unsigned, so
I've dropped that.
> /* Calculate the relative paths */
> basename = strrchr(progpath, '/');
> @@ -363,6 +368,79 @@ int main(int argc, char **argv)
> *cur++ = "-Wno-builtin-macro-redefined";
> }
> +#ifdef BR2_RELRO_FULL
> + /* Patterned after Fedora/Gentoo hardening approaches.
> + * https://fedoraproject.org/wiki/Changes/Harden_All_Packages
> + * https://wiki.gentoo.org/wiki/Hardened/Toolchain#Position_Independent_Executables_.28PIEs.29
> + *
> + * A few checks are added to enable disabling of PIE
enable disabling sounds quite confusing to me, so I've changed it to
"to allow disabling of PIE"
> + * 1) -fno-pie and -no-pie are used by other distros to disable PIE in
> + * cases where the compiler enables it by default. The logic below
> + * maintains that behavior.
> + * Ref: https://wiki.ubuntu.com/SecurityTeam/PIE
> + * 2) A check for -fno-PIE has been used in older Linux Kernel builds
> + * in a similar way to -fno-pie or -no-pie.
> + * 3) A check is added for Kernel and U-boot defines
> + * (-D__KERNEL__ and -D__UBOOT__).
> + */
> + for (i = 1; i < argc; i++) {
> + /* Apply all incompatible link flag and disable checks first */
> + if (!strcmp(argv[i], "-r") ||
> + !strcmp(argv[i], "-Wl,-r") ||
> + !strcmp(argv[i], "-static") ||
> + !strcmp(argv[i], "-D__KERNEL__") ||
> + !strcmp(argv[i], "-D__UBOOT__") ||
> + !strcmp(argv[i], "-fno-pie") ||
> + !strcmp(argv[i], "-fno-PIE") ||
> + !strcmp(argv[i], "-no-pie"))
> + break;
> + /* Record that shared was present which disables -pie but don't
> + * break out of loop as a check needs to occur that possibly
> + * still allows -fPIE to be set
> + */
> + if (!strcmp(argv[i], "-shared"))
> + found_shared = 1;
> + }
> + if (i == argc) {
It would IMHO have been a bit clearer to add the found_shared / -fpie
logic here right after the check, but OK.
> + /* Compile and link condition checking have been kept split
> + * between these two loops, as there maybe already valid
This also sounds a bit odd to me. I've added "are", E.G. "as there maybe
already are valid"
> + * compile flags set for position independence. In that case
> + * the wrapper just adds the -pie for link.
> + */
> + for (j = 1; j < argc; j++) {
There is not really any reason to use a different loop iteration
variable than 'i' here, so I've dropped the 'j' variable.
> + if (!strcmp(argv[j], "-fpie") ||
> + !strcmp(argv[j], "-fPIE") ||
> + !strcmp(argv[j], "-fpic") ||
> + !strcmp(argv[j], "-fPIC"))
> + break;
> + }
> + /* Both args below can be set at compile/link time
> + * and are ignored correctly when not used
> + */
Indentation looks a bit odd here, fixed.
> +#ifdef BR2_RELRO_FULL
> + *cur++ = "-Wl,-z,now";
> + *cur++ = "-Wl,-z,relro";
> +#endif
> + }
> +
Trailing spaces.
Committed with these minor fixes, thanks.
--
Bye, Peter Korsgaard
More information about the buildroot
mailing list