1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
|
# Copyright 1999-2008 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/eclass/hardened-funcs.eclass,v 1.001 2009/03/23 21:38:00 zorry Exp $
#
# Maintainer: Hardened Ninjas <hardened@gentoo.org>
inherit eutils toolchain-funcs
___ECLASS_RECUR_HARDENED_FUNCS="yes"
[[ -z ${___ECLASS_RECUR_FLAG_O_MATIC} ]] && inherit flag-o-matic
# Stuff for flag-o-matic.eclass
# Internal function for _filter-hardened
# _manage_hardened <flag being filtered> <cflag to use>
_manage-hardened() {
[[ -z $1 ]] && die "Internal hardened-funcs error - please report"
if test-flags "$1" > /dev/null ; then
elog "Hardened compiler will filter some flags"
_raw_append_flag $1
else
die "Compiler do not support $1"
fi
}
# inverted filters for hardened compiler. This is trying to unpick
# the hardened compiler defaults.
_filter-hardened() {
local f
for f in "$@" ; do
case "$f" in
# Ideally we should only concern ourselves with PIE flags,
# not -fPIC or -fpic, but too many places filter -fPIC without
# thinking about -fPIE.
-fPIC|-fpic|-fPIE|-fpie|-Wl,pie|-pie)
gcc-specs-pie && _manage-hardened -nopie ;;
-fstack-protector)
gcc-specs-ssp && _manage-hardened -fno-stack-protector ;;
-fstack-protector-all)
gcc-specs-ssp-to-all && _manage-hardened -fno-stack-protector-all ;;
-D_FORTIFY_SOURCE=2|-D_FORTIFY_SOURCE=1|-D_FORTIFY_SOURCE=0)
gcc-specs-fortify && _manage-hardened -U_FORTIFY_SOURCE ;;
-fno-strict-overflow)
gcc-specs-nostrict && _manage-hardened -fstrict-overflow ;;
esac
done
}
# Special case: -fno-stack-protector-all needs special management
# on hardened gcc-4.
_append-flag() {
[[ -z "$1" ]] && return 0
case "$1" in
-fno-stack-protector-all)
gcc-specs-ssp-to-all || continue
_manage-hardened -fno-stack-protector-all ;;
*)
_raw_append_flag "$1"
esac
}
# stuff form toolchain.eclass
get_gcc_src_uri_hardened() {
# PIE_VER
# PIE_GCC_VER
# obsoleted: PIE_CORE
# These variables control patching in various updates for the logic
# controlling Position Independant Executables. PIE_VER is expected
# to be the version of this patch, PIE_GCC_VER the gcc version of
# the patch, and PIE_CORE (obsoleted) the actual filename of the patch.
# An example:
# PIE_VER="8.7.6.5"
# PIE_GCC_VER="3.4.0"
# The resulting filename of this tarball will be:
# gcc-${PIE_GCC_VER:-${GCC_RELEASE_VER}}-piepatches-v${PIE_VER}.tar.bz2
# old syntax (do not define PIE_CORE anymore):
# PIE_CORE="gcc-3.4.0-piepatches-v${PIE_VER}.tar.bz2"
#
# ESPF_VER
# This is for the espf gcc 4 patches
#
# PP_VER
# PP_GCC_VER
# obsoleted: PP_FVER
# These variables control patching in stack smashing protection
# support. They both control the version of ProPolice to download.
#
# PP_VER / PP_GCC_VER
# Used to roll our own custom tarballs of ssp.
# PP_FVER / PP_VER
# Used for mirroring ssp straight from IBM.
# PP_VER sets the version of the directory in which to find the
# patch, and PP_FVER sets the version of the patch itself. For
# example:
# PP_VER="3_4"
# PP_FVER="${PP_VER//_/.}-2"
# would download gcc3_4/protector-3.4-2.tar.gz
export PIE_GCC_VER=${PIE_GCC_VER:-${GCC_RELEASE_VER}}
export PP_GCC_VER=${PP_GCC_VER:-${GCC_RELEASE_VER}}
[[ -n ${PIE_VER} ]] && \
PIE_CORE=${PIE_CORE:-gcc-${PIE_GCC_VER}-piepatches-v${PIE_VER}.tar.bz2}
# propolice aka stack smashing protection
if [[ -n ${PP_VER} ]] ; then
if [[ -n ${PP_FVER} ]] ; then
GCC_SRC_URI="${GCC_SRC_URI}
!nossp? (
http://www.research.ibm.com/trl/projects/security/ssp/gcc${PP_VER}/protector-${PP_FVER}.tar.gz
$(gentoo_urls protector-${PP_FVER}.tar.gz)
)"
else
GCC_SRC_URI="${GCC_SRC_URI} $(gentoo_urls gcc-${PP_GCC_VER}-ssp-${PP_VER}.tar.bz2)"
fi
fi
# strawberry pie, Cappuccino and a Gauloises (it's a good thing)
[[ -n ${PIE_VER} ]] && \
GCC_SRC_URI="${GCC_SRC_URI} !nopie? ( $(gentoo_urls ${PIE_CORE})
http://weaver.gentooenterprise.com/hardened/patches/gcc-${PIE_GCC_VER}-piepatches-v${PIE_VER}.tar.bz2
)"
# espf patch for gcc >4.3.3 compiler
[[ -n ${ESPF_VER} ]] && \
GCC_SRC_URI="${GCC_SRC_URI} ( $(gentoo_urls gcc-${GCC_RELEASE_VER}-espf-${ESPF_VER}.tar.bz2)
http://weaver.gentooenterprise.com/hardened/patches/gcc-${GCC_RELEASE_VER}-espf-${ESPF_VER}.tar.bz2
)"
# gcc minispec for the hardened gcc 4 compiler
[[ -n ${SPECS_VER} ]] && \
GCC_SRC_URI="${GCC_SRC_URI} ( $(gentoo_urls gcc-${GCC_RELEASE_VER}-specs-${SPECS_VER}.tar.bz2)
http://weaver.gentooenterprise.com/hardened/patches/gcc-${GCC_RELEASE_VER}-specs-${SPECS_VER}.tar.bz2
)"
}
# The gentoo pie,ssp and fortify patches allow for 4 configurations:
# 1) PIE+SSP by default
# 2) PIE by default
# 3) SSP by default
# 4) PIE+SSP+FORTIFY by default on gcc 4
hardened_gcc_works() {
if [[ $1 == "pie" ]] ; then
# $gcc_cv_ld_pie is unreliable as it simply take the output of
# `ld --help | grep -- -pie`, that reports the option in all cases, also if
# the loader doesn't actually load the resulting executables.
# To avoid breakage, blacklist FreeBSD here at least
[[ ${CTARGET} == *-freebsd* ]] && return 1
want_pie || return 1
hardened_gcc_is_stable pie && return 0
if tc_version_is_at_least 4.3.2 ; then
ewarn "PIE is not supported on this arch $(tc-arch)"
else
if has ~$(tc-arch) ${ACCEPT_KEYWORDS} ; then
hardened_gcc_check_unsupported pie && return 1
ewarn "Allowing pie-by-default for an unstable arch ($(tc-arch))"
return 0
fi
fi
return 1
elif [[ $1 == "ssp" ]] ; then
want_ssp || return 1
hardened_gcc_is_stable ssp && return 0
if tc_version_is_at_least 4.3.2 ; then
ewarn "SSP is not supported on this arch $(tc-arch)"
return 1
else
if has ~$(tc-arch) ${ACCEPT_KEYWORDS} ; then
hardened_gcc_check_unsupported ssp && return 1
ewarn "Allowing ssp-by-default for an unstable arch ($(tc-arch))"
return 0
fi
fi
return 1
elif [[ $1 == "fortify" ]] ; then
want_fortify || return 1
hardened_gcc_is_stable fortify && return 0
ewarn "Fortify is not supported on this $(tc-arch)"
return 1
else
# laziness ;)
hardened_gcc_works pie || return 1
hardened_gcc_works ssp || return 1
# This is needed for not to mess with gcc 3 and SSP
if tc_version_is_at_least 4.3.2 ; then
hardened_gcc_works fortify || return 1
fi
return 0
fi
}
hardened_gcc_is_stable() {
if tc_version_is_at_least 4.3.2 ; then
# For the new hardened setup in gcc 4.3 ebuild
if [[ $1 == "pie" ]] ; then
if [[ ${CTARGET} == *-uclibc* ]] && has ~$(tc-arch) ${PIE_UCLIBC_STABLE} || has ~$(tc-arch) ${PIE_GLIBC_STABLE} ; then
ewarn "Allowing pie-by-default for an untested arch $(tc-arch)" && return 0
elif [[ ${CTARGET} == *-uclibc* ]] && has $(tc-arch) ${PIE_UCLIBC_STABLE} || has $(tc-arch) ${PIE_GLIBC_STABLE} ; then
return 0
else
return 1
fi
elif [[ $1 == "ssp" ]] ; then
if [[ ${CTARGET} == *-uclibc* ]] && has ~$(tc-arch) ${SSP_UCLIBC_STABLE} || has ~$(tc-arch) ${SSP_STABLE} ; then
ewarn "Allowing ssp-by-default for an untested arch $(tc-arch)" && return 0
elif [[ ${CTARGET} == *-uclibc* ]] && has $(tc-arch) ${SSP_UCLIBC_STABLE} || has $(tc-arch) ${SSP_STABLE} ; then
return 0
else
return 1
fi
elif [[ $1 == "fortify" ]] ; then
if [[ ${CTARGET} == *-uclibc* ]] && has ~$(tc-arch) ${FORTIFY_UCLIBC_STABLE} || has ~$(tc-arch) ${FORTIFY_STABLE} ; then
ewarn "Allowing fortify-by-default for an untested arch $(tc-arch)" && return 0
elif [[ ${CTARGET} == *-uclibc* ]] && has $(tc-arch) ${FORTIFY_UCLIBC_STABLE} || has $(tc-arch) ${FORTIFY_STABLE} ; then
return 0
else
return 1
fi
else
die "hardened_gcc_stable needs to be called with pie, ssp or fortify"
fi
# For the old hardened gcc 3.4 ebuild
else
if [[ $1 == "pie" ]] ; then
# HARDENED_* variables are deprecated and here for compatibility
local tocheck="${HARDENED_PIE_WORKS} ${HARDENED_GCC_WORKS}"
if [[ ${CTARGET} == *-uclibc* ]] ; then
tocheck="${tocheck} ${PIE_UCLIBC_STABLE}"
else
tocheck="${tocheck} ${PIE_GLIBC_STABLE}"
fi
elif [[ $1 == "ssp" ]] ; then
# ditto
local tocheck="${HARDENED_SSP_WORKS} ${HARDENED_GCC_WORKS}"
if [[ ${CTARGET} == *-uclibc* ]] ; then
tocheck="${tocheck} ${SSP_UCLIBC_STABLE}"
else
tocheck="${tocheck} ${SSP_STABLE}"
fi
else
die "hardened_gcc_stable needs to be called with pie or ssp"
fi
hasq $(tc-arch) ${tocheck} && return 0
fi
return 1
}
espf_gcc_is_stable() {
if [[ ${CTARGET} == *-uclibc* ]] && has ~$(tc-arch) ${ETSPF_UCLIBC_STABLE} || has ~$(tc-arch) ${ESPF_GLIBC_STABLE} ; then
ewarn "Allowing espf as default for an untested arch $(tc-arch)" && return 0
elif [[ ${CTARGET} == *-uclibc* ]] && has $(tc-arch) ${ESPF_UCLIBC_STABLE} || has $(tc-arch) ${ESPF_GLIBC_STABLE} ; then
return 0
else
return 1
fi
}
# For the old hardened gcc 3.4 ebuild
hardened_gcc_check_unsupported() {
local tocheck=""
# if a variable is unset, we assume that all archs are unsupported. since
# this function is never called if hardened_gcc_is_stable returns true,
# this shouldn't cause problems... however, allowing this logic to work
# even with the variables unset will break older ebuilds that dont use them.
if [[ $1 == "pie" ]] ; then
if [[ ${CTARGET} == *-uclibc* ]] ; then
[[ -z ${PIE_UCLIBC_UNSUPPORTED} ]] && return 0
tocheck="${tocheck} ${PIE_UCLIBC_UNSUPPORTED}"
else
[[ -z ${PIE_GLIBC_UNSUPPORTED} ]] && return 0
tocheck="${tocheck} ${PIE_GLIBC_UNSUPPORTED}"
fi
elif [[ $1 == "ssp" ]] ; then
if [[ ${CTARGET} == *-uclibc* ]] ; then
[[ -z ${SSP_UCLIBC_UNSUPPORTED} ]] && return 0
tocheck="${tocheck} ${SSP_UCLIBC_UNSUPPORTED}"
else
[[ -z ${SSP_UNSUPPORTED} ]] && return 0
tocheck="${tocheck} ${SSP_UNSUPPORTED}"
fi
else
die "hardened_gcc_check_unsupported needs to be called with pie or ssp"
fi
hasq $(tc-arch) ${tocheck} && return 0
return 1
}
check_hardened_compiler_vanilla() {
# This situation is when we trying to build a non-hardened compiler with a
# hardened compiler.
if gcc-specs-pie || gcc-specs-ssp || gcc-specs-fortify && ! use hardened ; then
eerror "You have requested a non-hardened compiler, but you are using a hardened"
eerror "compiler to do so, which is inadvisable. If you really want to build a"
eerror "non-hardened compiler, switch to the vanilla compiler with gcc-config"
eerror "first."
die "You must build non-hardened compilers with vanilla-spec compilers."
fi
}
has_libssp() {
[[ -e /$(get_libdir)/libssp.so ]] && return 0
return 1
}
want_libssp() {
[[ ${GCC_LIBSSP_SUPPORT} == "true" ]] || return 1
has_libssp || return 1
[[ -n ${PP_VER} ]] || return 1
return 0
}
_want_stuff() {
local var=$1 flag=$2
[[ -z ${!var} ]] && return 1
use ${flag} && return 0
return 1
}
want_ssp() { _want_stuff PP_VER !nossp ; }
want_pie() { _want_stuff PIE_VER !nopie ; }
want_boundschecking() { _want_stuff HTB_VER boundschecking ; }
want_split_specs() { [[ ${SPLIT_SPECS} == "true" ]] && want_pie ; }
# Only supported on hardened gcc 4.3 and newer
want_fortify() { use hardened && libc_has_fortify && tc_version_is_at_least 4.2 && [[ -n ${SPECS_VER} ]] ; }
want_minispecs() {
if tc_version_is_at_least 4.3.2 && use hardened ; then
[[ -n ${SPECS_VER} ]] && want_pie && return 0
[[ -n ${ESPF_VER} ]] && [[ -n ${SPECS_VER} ]] && return 1
die "For Hardend to work you need the minispecs files and have the PIE patch"
fi
return 1
}
want_espf() {
if tc_version_is_at_least 4.3.3 && use hardened ; then
[[ -n ${ESPF_VER} ]] && [[ -n ${SPECS_VER} ]] && return 0
die "For Hardend to work you need the minispecs files and have the espf patch"
fi
return 1
}
# This function checks whether or not glibc has the support required to build
# Position Independant Executables with gcc.
glibc_have_pie() {
if [[ ! -f ${ROOT}/usr/$(get_libdir)/Scrt1.o ]] ; then
echo
ewarn "Your glibc does not have support for pie, the file Scrt1.o is missing"
ewarn "Please update your glibc to a proper version or disable hardened"
echo
return 1
fi
}
# This function determines whether or not libc has been patched with stack
# smashing protection support.
libc_has_ssp() {
[[ ${ROOT} != "/" ]] && return 0
# lib hacks taken from sandbox configure
echo 'int main(){}' > "${T}"/libctest.c
LC_ALL=C gcc "${T}"/libctest.c -lc -o libctest -Wl,-verbose &> "${T}"/libctest.log || return 1
local libc_file=$(awk '/attempt to open/ { if (($4 ~ /\/libc\.so/) && ($5 == "succeeded")) LIBC = $4; }; END {print LIBC}' "${T}"/libctest.log)
[[ -z ${libc_file} ]] && die "Unable to find a libc !?"
# Check for gcc-4.x style ssp support
if [[ -n $(readelf -s "${libc_file}" 2>/dev/null | \
grep 'FUNC.*GLOBAL.*__stack_chk_fail') ]]
then
return 0
else
# Check for gcc-3.x style ssp support
if [[ -n $(readelf -s "${libc_file}" 2>/dev/null | \
grep 'OBJECT.*GLOBAL.*__guard') ]] && \
[[ -n $(readelf -s "${libc_file}" 2>/dev/null | \
grep 'FUNC.*GLOBAL.*__stack_smash_handler') ]]
then
return 0
elif is_crosscompile ; then
die "'${libc_file}' was detected w/out ssp, that sucks (a lot)"
else
return 1
fi
fi
}
# My need to redo this lib check later.
# <zorry[@]ume.nu
libc_has_fortify() {
[[ ${ROOT} != "/" ]] && return 0
# lib hacks taken from sandbox configure
echo 'int main(){}' > "${T}"/libctest.c
LC_ALL=C gcc "${T}"/libctest.c -lc -o libctest -Wl,-verbose &> "${T}"/libctest.log || return 1
local libc_file=$(awk '/attempt to open/ { if (($4 ~ /\/libc\.so/) && ($5 == "succeeded")) LIBC = $4; }; END {print LIBC}' "${T}"/libctest.log)
[[ -z ${libc_file} ]] && die "Unable to find a libc !?"
# Check for gcc-4.x style fortify support
if [[ -n $(readelf -s "${libc_file}" 2>/dev/null | \
grep 'FUNC.*GLOBAL.*__fortify_fail') ]]
then
return 0
fi
}
# Defaults to enable for all hardened toolchains <gcc 4
gcc_common_hard="-DEFAULT_RELRO -DEFAULT_BIND_NOW"
# Configure to build with the hardened GCC 3 specs as the default
# Don't need it if we have minispec like gcc 4
make_gcc_hard() {
if hardened_gcc_works ; then
einfo "Updating gcc to use automatic PIE + SSP building ..."
sed -e "s|^HARD_CFLAGS = |HARD_CFLAGS = -DEFAULT_PIE_SSP ${gcc_common_hard} |" \
-i "${S}"/gcc/Makefile.in || die "Failed to update gcc!"
elif hardened_gcc_works pie ; then
einfo "Updating gcc to use automatic PIE building ..."
ewarn "SSP has not been enabled by default"
sed -e "s|^HARD_CFLAGS = |HARD_CFLAGS = -DEFAULT_PIE ${gcc_common_hard} |" \
-i "${S}"/gcc/Makefile.in || die "Failed to update gcc!"
elif hardened_gcc_works ssp ; then
einfo "Updating gcc to use automatic SSP building ..."
ewarn "PIE has not been enabled by default"
sed -e "s|^HARD_CFLAGS = |HARD_CFLAGS = -DEFAULT_SSP ${gcc_common_hard} |" \
-i "${S}"/gcc/Makefile.in || die "Failed to update gcc!"
else
# do nothing if hardened isnt supported, but dont die either
ewarn "hardened is not supported for this arch in this gcc version"
ebeep
return 0
fi
# Rebrand to make bug reports easier
BRANDING_GCC_PKGVERSION=${BRANDING_GCC_PKGVERSION/Gentoo/Gentoo Hardened}
}
# now we generate different spec files so that the user can select a compiler
# that enforces certain features in gcc itself and so we don't have to worry
# about a certain package ignoring CFLAGS/LDFLAGS
# Not needed if we use minispecs
_create_specs_file() {
# Usage: _create_specs_file <USE flag> <specs name> <CFLAGS>
local uflag=$1 name=$2 flags=${*:3}
ebegin "Creating a ${name} gcc specs file"
pushd "${WORKDIR}"/build/gcc > /dev/null
if [[ -z ${uflag} ]] || use ${uflag} ; then
# backup the compiler first
cp Makefile Makefile.orig
sed -i -e '/^HARD_CFLAGS/s:=.*:='"${flags}"':' Makefile
mv xgcc xgcc.foo
mv gcc.o gcc.o.foo
emake -s xgcc
$(XGCC) -dumpspecs > "${WORKDIR}"/build/${name}.specs
# restore everything to normal
mv gcc.o.foo gcc.o
mv xgcc.foo xgcc
mv Makefile.orig Makefile
else
$(XGCC) -dumpspecs > "${WORKDIR}"/build/${name}.specs
fi
popd > /dev/null
eend $([[ -s ${WORKDIR}/build/${name}.specs ]] ; echo $?)
}
create_vanilla_specs_file() { _create_specs_file hardened vanilla ; }
create_hardened_specs_file() { _create_specs_file !hardened hardened ${gcc_common_hard} -DEFAULT_PIE_SSP ; }
create_hardenednossp_specs_file() { _create_specs_file "" hardenednossp ${gcc_common_hard} -DEFAULT_PIE ; }
create_hardenednopie_specs_file() { _create_specs_file "" hardenednopie ${gcc_common_hard} -DEFAULT_SSP ; }
create_hardenednopiessp_specs_file() { _create_specs_file "" hardenednopiessp ${gcc_common_hard} ; }
split_out_specs_files() {
local s spec_list="hardenednopiessp vanilla"
if hardened_gcc_works ; then
spec_list="${spec_list} hardened hardenednossp hardenednopie"
elif hardened_gcc_works pie ; then
spec_list="${spec_list} hardenednossp"
elif hardened_gcc_works ssp ; then
spec_list="${spec_list} hardenednopie"
fi
for s in ${spec_list} ; do
create_${s}_specs_file || return 1
done
}
hardened_compiler_src_unpack_setup() {
# For the old gcc < 3.4
if ! tc_version_is_at_least 4.3 ; then
# Fail if using pie patches, building hardened, and glibc doesn't have
# the necessary support
want_pie && use hardened && glibc_have_pie
einfo "updating configuration to build GCC gcc-3 style"
make_gcc_hard || die "failed to make gcc hard"
fi
if tc_version_is_at_least 4.3.3 && use hardened ; then
if [[ ${PIE_VER} ]] ; then
glibc_have_pie || die "failed to make gcc hardened"
fi
if [[ ${ESPF_VER} ]] ; then
espf_gcc_is_stable || die "ESPF is not supported on this $(tc-arch) arch."
fi
# Rebrand to make bug reports easier
use hardened && BRANDING_GCC_PKGVERSION=${BRANDING_GCC_PKGVERSION/Gentoo/Gentoo Hardened}
fi
}
hardened_configure() {
# If we want hardened support on newer gcc
if tc_version_is_at_least 4.3.3 && use hardened ; then
[[ ${PIE_VER} ]] && confgcc="${confgcc} --enable-hardened"
[[ ${ESPF_VER} ]] && confgcc="${confgcc} --enable-espf"
else
[[ ${PIE_VER} ]] && confgcc="${confgcc} --disable-hardened"
[[ ${ESPF_VER} ]] && confgcc="${confgcc} --disable-espf"
fi
# If we want libssp support
if want_libssp ; then
confgcc="${confgcc} --enable-libssp"
else
[[ -z ${ESPF_VER} ]] && export gcc_cv_libc_provides_ssp=yes
confgcc="${confgcc} --disable-libssp"
fi
}
setup_minispecs_gcc_build_specs() {
# Setup the "specs" file for gcc to use when building.
if want_minispecs ; then
if hardened_gcc_works pie ; then
cat "${WORKDIR}"/specs/pie.specs >> "${WORKDIR}"/build.specs
fi
if hardened_gcc_works ssp ; then
for s in ssp sspall; do
cat "${WORKDIR}"/specs/${s}.specs >> "${WORKDIR}"/build.specs
done
fi
if hardened_gcc_works fortify ; then
cat "${WORKDIR}"/specs/fortify.specs >> "${WORKDIR}"/build.specs
fi
for s in nostrict znow ; do
cat "${WORKDIR}"/specs/${s}.specs >> "${WORKDIR}"/build.specs
done
export GCC_SPECS="${WORKDIR}"/build.specs
fi
}
setup_split_specs() {
# Do not create multiple specs files for PIE+SSP if boundschecking is in
# USE, as we disable PIE+SSP when it is.
# minispecs wil not need to split out specs.
if [[ ${ETYPE} == "gcc-compiler" ]] && want_split_specs && ! want_minispecs && ! want_espf ; then
split_out_specs_files || die "failed to split out specs"
fi
}
copy_minispecs_gcc_specs() {
# Build system specs file which, if it exists, must be a complete set of
# specs as it completely and unconditionally overrides the builtin specs.
# For gcc 4
if want_minispecs ; then
$(XGCC) -dumpspecs > "${WORKDIR}"/specs/specs
cat "${WORKDIR}"/build.specs >> "${WORKDIR}"/specs/specs
insinto ${LIBPATH}
doins "${WORKDIR}"/specs/*.specs && doins "${WORKDIR}"/specs/specs || die "failed to install specs"
fi
if want_espf ; then
insinto ${LIBPATH}
doins "${WORKDIR}"/specs/*.specs || die "failed to install specs"
fi
}
create_hardened_gcc_env_entry() {
# For the old gcc 3 and split_specs
if want_split_specs ; then
if use hardened ; then
create_gcc_env_entry vanilla
fi
! use hardened && hardened_gcc_works && create_gcc_env_entry hardened
if hardened_gcc_works || hardened_gcc_works pie ; then
create_gcc_env_entry hardenednossp
fi
if hardened_gcc_works || hardened_gcc_works ssp ; then
create_gcc_env_entry hardenednopie
fi
create_gcc_env_entry hardenednopiessp
insinto ${LIBPATH}
doins "${WORKDIR}"/build/*.specs || die "failed to install specs"
fi
# Setup the gcc_env_entry for hardened gcc 4 with minispecs or espf
if want_minispecs ; then
if hardened_gcc_works pie ; then
create_gcc_env_entry nopie
fi
if hardened_gcc_works ssp ; then
create_gcc_env_entry nossp_all
fi
if hardened_gcc_works fortify ; then
create_gcc_env_entry nofortify
fi
create_gcc_env_entry vanilla
fi
if want_espf ; then
create_gcc_env_entry nopie
create_gcc_env_entry nossp
create_gcc_env_entry nofortify
create_gcc_env_entry vanilla
fi
}
hardened_gcc_quick_unpack() {
export PIE_GCC_VER=${PIE_GCC_VER:-${GCC_RELEASE_VER}}
export PP_GCC_VER=${PP_GCC_VER:-${GCC_RELEASE_VER}}
export ESPF_GCC_VER=${ESPF_GCC_VER:-${GCC_RELEASE_VER}}
if want_ssp ; then
if [[ -n ${PP_FVER} ]] ; then
# The gcc 3.4 propolice versions are meant to be unpacked to ${S}
pushd "${S}" > /dev/null
unpack protector-${PP_FVER}.tar.gz
popd > /dev/null
fi
if [[ -n ${PP_VER} ]] ; then
unpack gcc-${PP_GCC_VER}-ssp-${PP_VER}.tar.bz2
fi
fi
if want_pie ; then
if [[ -n ${PIE_CORE} ]] ; then
unpack ${PIE_CORE}
else
unpack gcc-${PIE_GCC_VER}-piepatches-v${PIE_VER}.tar.bz2
fi
[[ -n ${SPECS_VER} ]] && \
unpack gcc-${GCC_RELEASE_VER}-specs-${SPECS_VER}.tar.bz2
fi
if want_espf ; then
unpack gcc-${GCC_RELEASE_VER}-espf-${ESPF_VER}.tar.bz2
unpack gcc-${GCC_RELEASE_VER}-specs-${SPECS_VER}.tar.bz2
fi
}
# Try to apply some stub patches so that gcc won't error out when
# passed parameters like -fstack-protector but no ssp is found
do_gcc_stub() {
local v stub_patch=""
for v in ${GCC_RELEASE_VER} ${GCC_BRANCH_VER} ; do
stub_patch=${GCC_FILESDIR}/stubs/gcc-${v}-$1-stub.patch
if [[ -e ${stub_patch} ]] && ! use vanilla ; then
EPATCH_SINGLE_MSG="Applying stub patch for $1 ..." \
epatch "${stub_patch}"
return 0
fi
done
}
# patch in ProPolice Stack Smashing protection
# GCC >4.1 have built in SSP support but may need some patch later.
do_gcc_SSP_patches() {
if ! tc_version_is_at_least 4.3.2 ; then
# PARISC has no love ... it's our stack :(
if [[ $(tc-arch) == "hppa" ]] || \
! want_ssp || \
(want_boundschecking && [[ ${HTB_EXCLUSIVE} == "true" ]])
then
do_gcc_stub ssp
return 0
fi
local ssppatch
local sspdocs
if [[ -n ${PP_FVER} ]] ; then
# Etoh keeps changing where files are and what the patch is named
if tc_version_is_at_least 3.4.1 ; then
# >3.4.1 uses version in patch name, and also includes docs
ssppatch="${S}/gcc_${PP_VER}.dif"
sspdocs="yes"
elif tc_version_is_at_least 3.4.0 ; then
# >3.4 put files where they belong and 3_4 uses old patch name
ssppatch="${S}/protector.dif"
sspdocs="no"
elif tc_version_is_at_least 3.2.3 ; then
# earlier versions have no directory structure or docs
mv "${S}"/protector.{c,h} "${S}"/gcc
ssppatch="${S}/protector.dif"
sspdocs="no"
fi
else
# Just start packaging the damn thing ourselves
mv "${WORKDIR}"/ssp/protector.{c,h} "${S}"/gcc/
ssppatch=${WORKDIR}/ssp/gcc-${PP_GCC_VER}-ssp.patch
# allow boundschecking and ssp to get along
(want_boundschecking && [[ -e ${WORKDIR}/ssp/htb-ssp.patch ]]) \
&& patch -s "${ssppatch}" "${WORKDIR}"/ssp/htb-ssp.patch
fi
[[ -z ${ssppatch} ]] && die "Sorry, SSP is not supported in this version"
epatch ${ssppatch}
if [[ ${PN} == "gcc" && ${sspdocs} == "no" ]] ; then
epatch "${GCC_FILESDIR}"/pro-police-docs.patch
fi
# Don't build crtbegin/end with ssp
sed -e 's|^CRTSTUFF_CFLAGS = |CRTSTUFF_CFLAGS = -fno-stack-protector |'\
-i gcc/Makefile.in || die "Failed to update crtstuff!"
# if gcc in a stage3 defaults to ssp, is version 3.4.0 and a stage1 is built
# the build fails building timevar.o w/:
# cc1: stack smashing attack in function ix86_split_to_parts()
if use build && tc_version_is_at_least 3.4.0 ; then
if gcc -dumpspecs | grep -q "fno-stack-protector:" ; then
epatch "${GCC_FILESDIR}"/3.4.0/gcc-3.4.0-cc1-no-stack-protector.patch
fi
fi
if want_libssp ; then
update_gcc_for_libssp
else
update_gcc_for_libc_ssp
fi
# Don't build libgcc with ssp
sed -e 's|^\(LIBGCC2_CFLAGS.*\)$|\1 -fno-stack-protector|' \
-i gcc/Makefile.in || die "Failed to update gcc!"
else
if [[ -n ${PP_VER} ]] ; then
guess_patch_type_in_dir "${WORKDIR}"/ssp
EPATCH_MULTI_MSG="Applying ssp patches ..." \
epatch "${WORKDIR}"/ssp
fi
fi
if ! want_espf ; then
gcc_has_native_ssp && BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, ssp"
[[ -n ${PP_VER} ]] || [[ -n ${PP_FVER} ]] && BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, ssp-${PP_FVER:-${PP_GCC_VER}-${PP_VER}}"
fi
}
# If glibc or uclibc has been patched to provide the necessary symbols itself,
# then lets use those for SSP instead of libgcc.
update_gcc_for_libc_ssp() {
if libc_has_ssp ; then
einfo "Updating gcc to use SSP from libc ..."
sed -e 's|^\(LIBGCC2_CFLAGS.*\)$|\1 -D_LIBC_PROVIDES_SSP_|' \
-i "${S}"/gcc/Makefile.in || die "Failed to update gcc!"
fi
}
# a split out non-libc non-libgcc ssp requires additional spec logic changes
update_gcc_for_libssp() {
einfo "Updating gcc to use SSP from libssp..."
sed -e 's|^\(INTERNAL_CFLAGS.*\)$|\1 -D_LIBSSP_PROVIDES_SSP_|' \
-i "${S}"/gcc/Makefile.in || die "Failed to update gcc!"
}
# do various updates to FORTIFY
do_gcc_FORTIFY_patches() {
if ! want_espf ; then
if hardened_gcc_works fortify ; then
BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, fortify"
fi
fi
}
# do various updates to PIE logic
do_gcc_PIE_patches() {
if [[ -z ${ESPF_VER} ]] ; then
if ! want_pie || \
(want_boundschecking && [[ ${HTB_EXCLUSIVE} == "true" ]])
then
return 0
fi
want_boundschecking \
&& rm -f "${WORKDIR}"/piepatch/*/*-boundschecking-no.patch* \
|| rm -f "${WORKDIR}"/piepatch/*/*-boundschecking-yes.patch*
use vanilla && rm -f "${WORKDIR}"/piepatch/*/*uclibc*
if tc_version_is_at_least 4.3.2 ; then
guess_patch_type_in_dir "${WORKDIR}"/piepatch
EPATCH_MULTI_MSG="Applying pie patches ..." \
epatch "${WORKDIR}"/piepatch
else
guess_patch_type_in_dir "${WORKDIR}"/piepatch/upstream
# corrects startfile/endfile selection and shared/static/pie flag usage
EPATCH_MULTI_MSG="Applying upstream pie patches ..." \
epatch "${WORKDIR}"/piepatch/upstream
# adds non-default pie support (rs6000)
EPATCH_MULTI_MSG="Applying non-default pie patches ..." \
epatch "${WORKDIR}"/piepatch/nondef
# adds default pie support (rs6000 too) if DEFAULT_PIE[_SSP] is defined
EPATCH_MULTI_MSG="Applying default pie patches ..." \
epatch "${WORKDIR}"/piepatch/def
# we want to be able to control the pie patch logic via something other
# than ALL_CFLAGS...
# Don't need it if we have minispec like gcc 4
sed -e '/^ALL_CFLAGS/iHARD_CFLAGS = ' \
-e 's|^ALL_CFLAGS = |ALL_CFLAGS = $(HARD_CFLAGS) |' \
-i "${S}"/gcc/Makefile.in
fi
BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, pie-${PIE_VER}"
fi
}
# do various updates to ESPF
do_gcc_ESPF_patches() {
if [[ -n ${ESPF_VER} ]] ; then
guess_patch_type_in_dir "${WORKDIR}"/espf-gcc-"${GCC_RELEASE_VER}"
EPATCH_MULTI_MSG="Applying espf patches ..." \
epatch "${WORKDIR}"/espf-gcc-"${GCC_RELEASE_VER}"
BRANDING_GCC_PKGVERSION="${BRANDING_GCC_PKGVERSION}, espf-${ESPF_VER}"
fi
}
exclude_hardened_gcc_patches() {
# PIEPATCH_EXCLUDE
# List of filenames, relative to ${WORKDIR}/piepatch/
# Travis Tilley <lv@gentoo.org> (03 Sep 2004)
#
for i in ${PIEPATCH_EXCLUDE} ; do
if [[ -f ${WORKDIR}/piepatch/${i} ]] ; then
einfo "Excluding piepatch ${i}"
rm -f "${WORKDIR}"/piepatch/${i} || die "failed to delete ${i}"
fi
done
}
|