Disclaimer :
This document is a work in progress and should not be considered official yet.
|
GCC-4/GLIBC-2.5 Hardened Toolchain Overview and Upgrade Guide (EARLY DRAFT)
1.
Introduction
Rationale for re-working the hardened toolchain.
The gcc-3/glibc-2.3 toolchain has been working reasonably well for
Hardened Gentoo
for a few years now. However while it has gained in maturity, there are a
number of known issues that have proven unresolvable so far. Most issues are
relatively minor and only show up in rare circumstances, however it has become
increasingly clear that the Stack Smash Protector (SSP) implementation in gcc-3
that was developed at IBM has some serious issues most especially with code
constructs of C++ (and also C, where gcc permits some C++ idioms to be used also
in C).
In gcc-4, Richard Henderson and others at RedHat
completely re-implemented
the stack smash protector, making a number of improvements in the process.
Internally to GCC, the implementation is significantly different, although the
end result and the behaviour of the generated object code is much the same.
Unfortunately, the re-implementation did not retain binary compatibility with
the implementation we used previously, so we could not just simply bump our
patches to support the newer toolchain without doing some work.
It was also clear that migrating to gcc-4 was not going to be trivial for the
standard Gentoo product, let alone Hardened Gentoo. Other changes to gcc (the
reason it gained a major version number increment) highlighted much code that
worked on gcc-3 often for the wrong reasons, but failed with gcc-4. Thus it
seemed like the ideal opportunity to re-examine the hardened toolchain
modifications to see if it could be done better and more consistently, since it
was apparent it would be some time before gcc-4 could be considered practical.
While the overall concepts for the hardened toolchain are largely the same, a
significant amount of work has gone into this task leading to hopefully a more
reliable and maintainable product. Hopefully it was worth it!
Overview of the gcc-4/glibc-2.5/binutils-2.17 toolchain for Hardened Gentoo
As mentioned above, the SSP implementation has changed substantially. Changes
to the interfaces used by gcc to handle stack overflows, and changes to the
semantics of the stack-protector compiler switches, have lead to modifications
of glibc so that it can support both the old and new interfaces, and
modifications to the way the SSP compiler switches are managed to avoid having
to modify ebuilds.
The other major plank of the hardened toolchain with respect to gcc, Position
Independent Executables (PIEs) has not changed; the support in gcc-4 is no
different from the support in gcc-3 which has been maintained upstram. However,
in order to support the default-PIE some changes have been made which should
mean that building executables will always use a consistent set of startfiles
and libraries. Previously there were occasions where odd results were observed;
particularly when building "-static". Static builds now result in a static/PIE
hybrid executable that should be stable on all architectures.
The other two elements of the hardened toolchain, RELRO and BIND_NOW, are
effectively no different than they were before.
In addition to the support changes necessary for SSP and the PIE cleanup, the
way compiler "specs" are handled ("specs" are configuration text used by the
compiler driver to control how the various components; the C compiler, C++
compiler, linker, assembler etc are invoked) has been reworked. Previously we
patched the compiler driver code significantly to inject our altered default
specs, and did so repeatedly in various combinations to get us the several
variants of the hardened compiler that are provided. The new approach still
patches the compiler driver, but once only and much, much less intrusively,
adding "call-outs" to "mini-specs" that are by default defined to behave as the
vanilla compiler does, but can be easily overridden to achieve the hardened
toolchain behaviour we desire. The altered specs are managed by appending
re-definitions of these "mini-specs" to the standard specs, overriding the
defaults in a much less architecture-dependent way.
A detailed description of the new toolchain modifications can be found in the
Technical Description of the Gentoo Hardened Toolchain.
2.
Upgrade Guide
Dependencies
There are a number of build and run-time dependencies between the various toolchain
elements. A brief elaboration of these will make it clear why the recommended
upgrade path is as it is.
- Hardened gcc-4 requires glibc-2.5 for ssp support functions
- The new reliable "static PIE" support means hardened glibc-2.5 must be built with hardened gcc-4
- "static PIE" support requires binutils-2.17
Of particular note, is the circular dependency between hardened gcc-4 and hardened glibc-2.5.
Note that these dependencies are only relevant when hardened.
Upgrade Sequence
The upgrade path is quite simple really. Upgrade to binutils-2.17 if necessary,
and ensure it is selected. Then, using the vanilla compiler, build both glibc
and gcc non-hardened - this installs all the support necessary to build them
hardened. Next, switch to the new compiler -hardened variant, rebuild glibc
and gcc. Ensure the hardened compiler is selected (reselect to be sure).
Switch off distcc and ccache if you're using them, to be sure you don't get mixed
results from previous compilations (especially if you have tried earlier versions
of the toolchain upgrade from overlays).
In detail, the steps are:
Ensure sys-devel/binutils-2.17 is installed:
Code Listing2.1: Check binutils version |
binutils-config -l
|
If the version selected (highlighted with '*') is 2.17, that's enough. If 2.17 is
installed but not selected, select it with binutils-config - otherwise merge it:
Code Listing2.2: Merge binutils-2.17 |
emerge --oneshot =sys-devel/binutils-2.17
|
and switch to it if necessary using binutils-config. Next, switch to the vanilla gcc:
Code Listing2.3: Select vanilla gcc |
gcc-config -l
gcc-config <current gcc>-vanilla
source /etc/profile
|
replacing <current gcc> with the current compiler name (or just choose the right number from the list).
Merge vanilla glibc-2.5 and gcc-4:
Code Listing2.4: Merging vanilla toolchain |
USE="-hardened" emerge --oneshot =sys-libs/glibc-2.5
USE="-hardened" emerge --oneshot =sys-devel/gcc-4.1.2
|
There are a number of known test failures with both glibc and gcc on a hardened
system. The glibc build will stop after the test failures. Complete the glibc
build either using ebuild (if you know what you're doing) or do the build again
with FEATURES="-test". The gcc build will carry on regardless, it'll
install and merge despite the failures. Once both are installed, switch to
the hardened gcc:
Code Listing2.5: Select hardened gcc |
gcc-config -l
gcc-config <new gcc>-hardened
source /etc/profile
|
replacing <new gcc> with the new compiler name.
Merge hardened glibc-2.5 and gcc-4:
Code Listing2.6: 5: Merging hardened toolchain |
emerge --oneshot =sys-libs/glibc-2.5
emerge --oneshot =sys-devel/gcc-4.1.2
|
Rebuild world with the new toochain:
Code Listing2.7: 6: Rebuilding world |
emerge -e world
|
That last - rebuilding world - does not have to be done immediately; existing
binaries should continue to run correctly against the upgraded glibc, and
portage should have left your previous compile in place since it's a major
revision change. It is probably a good idea to rebuild binutils with the new
toolchain (repeat 2.2) at least. See also the standard
Gentoo GCC Upgrade Guide
advice on common GCC upgrade pitfalls.
3.
References
Other Gentoo Documentation
The contents of this document, unless otherwise expressly stated, are licensed under the CC-BY-SA-2.5 license. The Gentoo Name and Logo Usage Guidelines apply.
|