The GCC package contains the GNU compiler collection, which includes the C and C++ compilers. The Binutils package contains a linker, an assembler, and other tools for handling object files.
This package is known to have issues when its default optimization flags (including the -march and -mtune options) are changed. If any environment variables that override default optimizations have been defined, such as CFLAGS and CXXFLAGS, unset them when building GCC.
Unpack the binutils-2.17, gcc-core-4.1.2, gcc-g++-4.1.2, and gcc-testsuite-4.1.2 source packages but do not change directory. Then combine the two packages to the same directory with the following commands:
mv -v gcc-4.1.2/ butterfly-toolchain
mv -v binutils-2.17 butterfly-toolchain/
cd butterfly-toolchain/
ln -vs binutils-2.17/{bfd,binutils,gas,gprof,ld,opcodes} .
Patch Binutils for mkstemp(3):
patch -Np1 -i ../binutils-2.17-hardened_tmp-3.patch
This patch is from the “binutils-2_17-branch” CVS branch. This branch is open for bug fixes only, and does not add any new features. Apply this patch with the following command:
patch -Np1 -i ../binutils-2.17-branch_update-1.patch
Patch to add -z lazy:
patch -Np1 -i ../binutils-2.17-lazy-1.patch
Patch Binutils for PT_PAX_FLAGS:
cd binutils-2.17/ patch -Np1 -i ../../binutils-2.17-pt_pax-1.patch cd ..
Make the head and tail command syntax Posix compliant:
Apply these patches for uClibc support. The locale patch is needed even if you have disabled locale support:
cd binutils-2.17/ patch -Np1 -i ../../binutils-2.17-uClibc_conf-1.patch cd ../ patch -Np1 -i ../gcc-4.1.2-uClibc_conf-1.patch patch -Np1 -i ../gcc-4.1.2-uClibc_locale-1.patch
Use this command to hardcode LIBS="-lintl":
sed -e 's/%{shared:-lc}/%{!nointl: -lintl} &/' \
-i gcc/config/linux.h
sed 's/head -1/head -n 1/g' -i.orig libstdc++-v3/configure
sed 's/head -1/head -n 1/g' -i.orig ltcf-c.sh
sed 's/head -1/head -n 1/g' -i.orig ltcf-gcj.sh
sed 's/tail +16c/tail -c +16/g' -i.orig configure
sed 's/tail +16c/tail -c +16/g' -i.orig gas/Makefile.in
sed 's/tail +16c/tail -c +16/g' -i.orig gcc/Makefile.in
sed 's/tail -3/tail -n 3/g' -i.orig gcc/configure
sed 's/tail +140/tail -n +140/g' -i.orig \
ld/testsuite/ld-bootstrap/bootstrap.exp
Fix the RPATH_ENVVAR for bfd and opcode:
sed -e 's@/.:$$r@/.libs:$$r@' -e 's@/.:@/.libs:@' -i.orig Makefile.in
Copy over the hardened-specs.h file previously installed to /tools from the Section 5.9, “Cocoon Toolchain.” page include it in gcc.c:
cp -v /tools/hardened-specs.h gcc/
sed '0,/.*config.h can define.*/s//#include "hardened-specs.h"\n&/' \
-i.orig gcc/gcc.c
Disable the fixincludes script and -Werror option:
sed 's@\./fixinc\.sh@-c true@' -i.orig2 gcc/Makefile.in sed 's/@WERROR@/-Wno-error/' -i.orig fixincludes/Makefile.in
Disable -fstack-protector[-all] in libssp.[a,so]:
sed 's/^AM_CFLAGS =/& -fno-stack-protector/' \
-i.orig libssp/Makefile.in
Disable -fstack-protector[-all] in libgcc.[a,so]:
sed 's/^LIBGCC2_CFLAGS =/& -fno-stack-protector/' \
-i.orig3 gcc/Makefile.in
Disable -fstack-protector[-all] in crtbegin[,S,T].o and crtend[,S].o:
sed 's/^CRTSTUFF_CFLAGS =/& -fno-stack-protector/' \
-i.orig4 gcc/Makefile.in
The mudflap debugging feature included with GCC will normally allow a program to continue running during violations to give the user more information. The following command will change this default behaviour so libmudflap will send an ABRT signal to abort the program. This can be reset with the MUDFLAP_OPTIONS environment variable. Please keep in mind that mudflap is a debugging feature, and was not intended as a security feature, and is being implemented like this here because this is better than not using it at all. This modification can be circumvented by a user setting the LD_PRELOAD environment variable to load an alternate libmudflap library:
sed 's/violation_mode = viol_nop/violation_mode = viol_abort/' \
-i.orig libmudflap/mf-runtime.c
Create a separate build directory again:
mkdir -v ../butterfly-build cd ../butterfly-build
Prepare for compilation:
../butterfly-toolchain/configure --prefix=/usr \
--libexecdir=/usr/lib --enable-shared \
--enable-threads=posix --enable-__cxa_atexit \
--enable-clocale=gnu --enable-languages=c,c++ \
--enable-checking --disable-werror
Compile the package:
make tooldir=/usr
The meaning of the make parameter:
Normally, the tooldir (the directory where the executables will ultimately be located) is set to $(exec_prefix)/$(target_alias). For example, i686 machines would expand that to /usr/i686-pc-linux-gnu. Because this is a custom system, this target-specific directory in /usr is not required. $(exec_prefix)/$(target_alias) would be used if the system was used to cross-compile (for example, compiling a package on an Intel machine that generates code that can be executed on PowerPC machines).
To test the results:
make -k check
There is an SSP test in gcc.misc-tests/. The testsuite will be very bad. SSP and PIC need to be disabled in CFLAGS_FOR_TARGET, and -L/usr/lib/static probably needs to be added so static libraries can be used.
Install the package:
make tooldir=/usr install
If you plan to link suid packages to libmudflap then you need to move the mudflap libraries to /lib with the following command:
mv -v /usr/lib/libmudflap{,th}.so* /lib
ln -vsf ../../lib/libmudflap.so.0 /usr/lib/libmudflap.so
ln -vsf ../../lib/libmudflapth.so.0 /usr/lib/libmudflapth.so
Move the static libraries installed by GCC:
mv -v /usr/lib/{libsupc++,libstdc++}.a /usr/lib/static/
mv -v /usr/lib/{libbfd,libiberty,libmudflap,libmudflapth}.a /usr/lib/static
mv -v /usr/lib/{libopcodes,libssp,libssp_nonshared}.a /usr/lib/static
mv -v /usr/lib/gcc/$(gcc -dumpmachine)/4.1.2/libgcov.a /usr/lib/static/
mv -v /usr/lib/libstdc++_pic.a /usr/lib/static/
Some packages expect the C PreProcessor to be installed in the /lib directory. To support those packages, create this symlink:
ln -vs ../usr/bin/cpp /lib
Many packages use the name cc to call the C compiler. To satisfy those packages, create a symlink:
ln -vs gcc /usr/bin/cc
Install the libiberty header file that is needed by some packages:
install -v -m0644 ../butterfly-toolchain/include/libiberty.h \
/usr/include
Confirm the new compiler is defining PIC, SSP, FORTIFY_SOURCE, and OPTIMIZE:
echo | cc -dM -E - | grep -E 'PIC|SSP|FORTIFY|OPTIMIZE'
This should return:
#define __OPTIMIZE__ 1 #define _FORTIFY_SOURCE 2 #define __SSP_ALL__ 2 #define __PIC__ 1
Test the _FORTIFY_SOURCE feature with the following program:
cat > strcpy-overflow.c << "EOF"
#include <string.h>
int main()
{
char buf[2];
strcpy(buf,"12345");
return 0;
}
EOF
gcc -o fortify-test strcpy-overflow.c
This should return:
strcpy-overflow.c: In function 'main': strcpy-overflow.c:5: warning: call to __builtin___strcpy_chk will always overflow destination buffer
It's worth mentioning here that the -Werror GCC option would cause this gcc to fail, and the program would not be created.
Try to run the program:
./fortify-test ; echo $?
This should return:
*** buffer overflow detected ***: ./fortify-test terminated
Followed by "Backtrace" and "Memory map", and the final two lines should say "Aborted" and "134"
In this fortify-test program the strcpy() function was replaced with the __strcpy_chk() function at compile time, when the warning was generated. The __strcpy_chk() function then aborted the program at run time when a buffer overflow was detected.
This particular program can also be used to test the Stack Smashing Protector. Recompile this program with optimizations disabled and FORTIFY_SOURCE enabled, which will override the GCC specs, simply to show that FORTIFY_SOURCE only works with optimizations:
gcc -o ssp-test strcpy-overflow.c -O0 -D_FORTIFY_SOURCE=2
Then run it:
./ssp-test ; echo $?
This should return:
*** stack smashing detected ***: ./ssp-test terminated Aborted 134