Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 829165 - sys-boot/grub-2.06-r1: build failure with clang and LDFLAGS="-pie"
Summary: sys-boot/grub-2.06-r1: build failure with clang and LDFLAGS="-pie"
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal
Assignee: Mike Gilbert
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-12-14 13:02 UTC by nvinson234
Modified: 2021-12-15 04:56 UTC (History)
2 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments
grub-2.06-clang-hardening.patch (grub-2.06-clang-hardening.patch,874 bytes, patch)
2021-12-14 13:06 UTC, nvinson234
Details | Diff
grub-2.06-r1.ebuild (grub-2.06-r1.ebuild,7.97 KB, text/plain)
2021-12-14 13:09 UTC, nvinson234
Details
grub.default-5 (grub.default-5,2.63 KB, text/plain)
2021-12-14 13:10 UTC, nvinson234
Details

Note You need to log in before you can comment on or make changes to this bug.
Description nvinson234 2021-12-14 13:02:18 UTC
When building grub-2.06-r1 using clang and ld.lld with hardended flags, ld.lld fails to link with the error:

    ld.lld: error: can't create dynamic relocation R_X86_64_64 against local symbol in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output

CFLAGS and CXXFLAGS are set to:

    -march=native -O2 -pipe -fPIC -fstack-protector-strong -D_FORTIFY_SOURCE=2


LDFLAGS is set to:
    "-Wl,-O1 -Wl,--as-needed -fuse-ld=lld -rtlib=compiler-rt -unwindlib=libunwind -pie"

Reproducible: Always

Steps to Reproduce:
1. Emerge the clang toolchain as described at https://wiki.gentoo.org/wiki/Clang
2. Build GRUB with clang toolchain
3. Observe errror
Actual Results:  
GRUB fails to build as ld.lld cannot create the required relocation records needed to link successfully.

Expected Results:  
GRUB builds successfully.
Comment 1 nvinson234 2021-12-14 13:06:39 UTC
Created attachment 758930 [details, diff]
grub-2.06-clang-hardening.patch

This patch modifies GRUB's configure script so --enable-stack-protector can be passed in unconditionally.  If a GRUB platform does not support the flag, configure will now disable the option instead of aborting.

This change allows the ebuild changes to work correctly.
Comment 2 nvinson234 2021-12-14 13:09:51 UTC
Created attachment 758931 [details]
grub-2.06-r1.ebuild

Updated ebuild to enable GRUB's hardening settings. It introduces a new USE flag to control the setting.  All versions of GCC that Gentoo supports also support stack-protector and are build with it implicitly enabled, so defaulting the flag to enabled should not cause any problems.

This updated ebuild also contains the fix for bug 711072
Comment 3 nvinson234 2021-12-14 13:10:54 UTC
Created attachment 758932 [details]
grub.default-5

This file is not related to the stated issue. I am including it so the ebuild I provided can be used without modification.

grub.default-5 fixes bug 711072
Comment 4 nvinson234 2021-12-14 13:12:02 UTC
All the proposed fixes I added for GRUB can also be found at https://github.com/nvinson/magpie/tree/master/sys-boot/grub.  I have used this repository to build test these changes.
Comment 5 Mike Gilbert gentoo-dev 2021-12-14 16:20:37 UTC
Please provide a build log showing the failure.
Comment 6 Mike Gilbert gentoo-dev 2021-12-14 16:36:24 UTC
Comment on attachment 758930 [details, diff]
grub-2.06-clang-hardening.patch

Please send this upstream.
Comment 7 Mike Gilbert gentoo-dev 2021-12-14 16:46:12 UTC
I really don't like this approach. We should be able to resolve this without adding a mostly pointless USE flag.
Comment 8 Mike Gilbert gentoo-dev 2021-12-14 17:40:59 UTC
I can reproduce the link failure with the following settings:

CC=clang
CFLAGS="-O2 -pipe -fPIC"
LDFLAGS="-Wl,--as-needed -pie"

The "-pie" in LDFLAGS is key. lld doesn't actually matter.

The failure seems to happen when host utilities are linked against gnulib. Most of the objects are compiled using CFLAGS. However, CFLAGS don't seem to get used when compiling gnulib.

Relevant output:

> clang -DHAVE_CONFIG_H -I. -I/x/portage/sys-boot/grub-2.06-r1/work/grub-2.06/grub-core/lib/gnulib -I../../..   -D_FILE_OFFSET_BITS=64   -c -o argp-help.o /x/portage/sys-boot/grub-2.06-r1/work/grub-2.06/grub-core/lib/gnulib/argp-help.c
> clang -std=gnu99 -O2 -pipe -fPIC -Wall -W -Wshadow -Wpointer-arith -Wundef -Wchar-subscripts -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wmain -Wmissing-braces -Wmissing-format-attribute -Wmultichar -Wparentheses -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wswitch -Wtrigraphs -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value  -Wunused-variable -Wwrite-strings -Wnested-externs -Wstrict-prototypes -Wcast-align  -Wextra -Wattributes -Wendif-labels -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wmissing-field-initializers -Wnonnull -Woverflow -Wvla -Wpointer-to-int-cast -Wstrict-aliasing -Wvariadic-macros -Wvolatile-register-var -Wpointer-sign -Wmissing-include-dirs -Wmissing-prototypes -Wmissing-declarations -Wformat=2 -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion   -Wl,--as-needed -pie    -o grub-mkimage util/grub_mkimage-grub-mkimage.o util/grub_mkimage-mkimage.o util/grub_mkimage-grub-mkimage32.o util/grub_mkimage-grub-mkimage64.o util/grub_mkimage-resolve.o grub-core/kern/emu/grub_mkimage-argp_common.o grub-core/osdep/grub_mkimage-init.o grub-core/osdep/grub_mkimage-config.o util/grub_mkimage-config.o  libgrubmods.a libgrubgcry.a libgrubkern.a grub-core/lib/gnulib/libgnu.a -llzma  -ldevmapper
> /usr/bin/x86_64-pc-linux-gnu-ld: grub-core/lib/gnulib/libgnu.a(argp-help.o): relocation R_X86_64_32S against `.data' can not be used when making a PIE object; recompile with -fPIE

Everything magically works with GCC because Gentoo configures GCC to emit PIE-compatible code by default.
Comment 9 nvinson234 2021-12-14 18:06:49 UTC
(In reply to Mike Gilbert from comment #7)
> I really don't like this approach. We should be able to resolve this without
> adding a mostly pointless USE flag.

The only alternative I could think to do is to check for '-pie' in LDFLAGS and check that the compiler is clang. However, if someone is trying to disable hardening when building GRUB, this approach would could mask that the attempt failed.  That said, the ebuild would have to know how to compute the "effective" LDFLAGS so it doesn't get tripped up on things like "-pie -no-pie".
Comment 10 Mike Gilbert gentoo-dev 2021-12-14 18:41:41 UTC
I see two possible solutions:

1. Fix the build system so that gnulib is built using CFLAGS.

2. Unconditionally remove "-pie" from LDFLAGS. This would result in a non-PIE build with clang, but that's better than a build failure.
Comment 11 Mike Gilbert gentoo-dev 2021-12-14 19:40:22 UTC
This is complicated by the variable manipulation we do in src_configure. We copy CFLAGS/LDFLAGS into HOST_CFLAGS/HOST_LDFLAGS, and then unset CFLAGS and LDFLAGS. 

This is done to prevent CFLAGS/LDFLAGS from leaking into grub-core objects, which are very sensitive to various compiler options. Instead, we allow configure.ac to populate TARGET_CFLAGS and TARGET_LDFLAGS.

Most of grub's build system uses HOST_CFLAGS and HOST_LDFLAGS or TARGET_CFLAGS and TARGET_LDFLAGS, but gnulib is an exception: it uses CFLAGS and LDFLAGS directly.
Comment 12 nvinson234 2021-12-15 03:55:05 UTC
(In reply to Mike Gilbert from comment #10)
> 2. Unconditionally remove "-pie" from LDFLAGS. This would result in a
> non-PIE build with clang, but that's better than a build failure.

That is what the proposed updated ebuild is doing now. It filters (via flag-o-matic's filter-flags command) -pie along with -fPIC, -fPIE, -fpic, -fpie, and -fstack-protector* before doing anything else in src_configure(). The point of filtering those flags is to reduce the likelihood of a bad GRUB build.

The 'stack-protection' USE flag controls whether '--enable-stack-protection stack-protector=strong' is passed to GRUB's configure script or not.  I default the USE flag to on because I think that it'll ensure the same hardening features are enabled when using both clang and gcc compilers.

As an aside, I'm not set on the USE flag's name. I have no objection to changing its name if there is a preference to call it something else or to use an existing USE flag. When I did a (admittedly quick) USE flag scan, I didn't see any that felt like a good fit.
Comment 13 Larry the Git Cow gentoo-dev 2021-12-15 04:56:56 UTC
The bug has been closed via the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=7c1b967ad02495722e66e18e2e6645388cf384e3

commit 7c1b967ad02495722e66e18e2e6645388cf384e3
Author:     Mike Gilbert <floppym@gentoo.org>
AuthorDate: 2021-12-15 04:54:32 +0000
Commit:     Mike Gilbert <floppym@gentoo.org>
CommitDate: 2021-12-15 04:56:54 +0000

    sys-boot/grub: remove '-pie' from LDFLAGS
    
    Closes: https://bugs.gentoo.org/829165
    Signed-off-by: Mike Gilbert <floppym@gentoo.org>

 sys-boot/grub/grub-2.06-r1.ebuild | 3 +++
 sys-boot/grub/grub-9999.ebuild    | 3 +++
 2 files changed, 6 insertions(+)