1 |
On Mon, 8 Jan 2007 13:46:51 +0100 (CET) |
2 |
"Peter S. Mazinger" <ps.m@×××.net> wrote: |
3 |
|
4 |
> On Sat, 6 Jan 2007, Kevin F. Quinn wrote: |
5 |
> |
6 |
> > [...] |
7 |
> > What we mess up, is that gcc's configure thinks that the compiler |
8 |
> > always generates PIC code (which it doesn't, quite) and thus |
9 |
> > doesn't do -fPIC -DPIC in places where it normally would do (it |
10 |
> > just does -DPIC). This means that some objects that should be built |
11 |
> > PIC, get built PIE with the hardened compiler. Historically there |
12 |
> > was a -D_IN_GCC_ (or something like that) filter in the specs which |
13 |
> > meant that sometimes gcc generated PIE code and sometimes not, |
14 |
> > depending on what part of gcc is being built. |
15 |
> > |
16 |
> > In order to have gcc build all its intermediate executables PIE |
17 |
> > (and to be honest, I don't see any point in doing so), in a way |
18 |
> > that works on all architectures, we would have to modify the build |
19 |
> > process a lot more than we already do. |
20 |
> |
21 |
> If we want to have gcc's final binaries "hardened", then we can't |
22 |
> probably avoid compiling the intermediate files "hardened" too, else |
23 |
> we have to tweak too many parts of the build-system. Some will |
24 |
> probably say that gcc is not needed hardened itself, because it is |
25 |
> not used for runtime (exceptions being |
26 |
> libgcc.a/libgcc_s.so/libsupc++.a/libstdc++.* and the crt files that |
27 |
> go into each binary), I personally think that it is a good test for |
28 |
> hardened to see if gcc fails somewhere, thus warning us about |
29 |
> expected problems. |
30 |
|
31 |
Well, building PIE doesn't find anything as such. My preference at the |
32 |
moment is to build gcc itself with SSP, NOW and RELRO (which don't |
33 |
have any conflict from one stage to the next), but not PIE. glibc I'm |
34 |
building with both SSP and PIE switched off. |
35 |
|
36 |
The crt files should definitely never be built -fPIE. For the lib*.a |
37 |
provided by gcc and libc, it may be worth building them both PIE and |
38 |
no-PIE. How they would be selected on use is another problem... |
39 |
|
40 |
> > > [...] |
41 |
> > > No, the code needs to be PIC, else the generated PIE binary has |
42 |
> > > text relocation (PIE binary is more like a shared library needing |
43 |
> > > though an interpreter/dynamic loader). |
44 |
> > |
45 |
> > The only time this is an issue is when lib*.a archives are being |
46 |
> > used to link executables. This is rather rare - indeed the only |
47 |
> > places I've seen it done are in gcc and glibc. |
48 |
> > |
49 |
> > |
50 |
> > ok; maybe I wasn't clear: |
51 |
> > |
52 |
> > 1) Objects to be linked into shared libraries must be PIC |
53 |
> > |
54 |
> > 2) Objects to be linked into position-independent executables |
55 |
> > should be PIE (but PIC objects are work too, they just put more |
56 |
> > through the PLT than necessary) |
57 |
> > |
58 |
> > 3) Objects to be linked into normal executables (i.e. not PIEs) |
59 |
> > should be normal - neither PIC nor PIE. |
60 |
> > |
61 |
> > I think you'll agree those statements are true. |
62 |
> |
63 |
> not with 2) |
64 |
> if that would be true, then the intermediate files would not have |
65 |
> text relocations, libiberty.a's objects are compiled -fPIE instead of |
66 |
> -fPIC (-DPIC does not influence the result) |
67 |
|
68 |
|
69 |
If it's false, then we're in trouble - because PIEs would always have |
70 |
textrels. |
71 |
|
72 |
The way to build a PIE, as I understand it, is to: |
73 |
|
74 |
(1) compile all objects -fPIE |
75 |
(2) link with -fPIE -pie |
76 |
|
77 |
If that creates executables with textrels, then we're in trouble |
78 |
everywhere. However I don't think that's the case - I understand we |
79 |
get textrels when: |
80 |
|
81 |
a) linking normal or -fPIE objects into shared libraries |
82 |
b) linking normal objects in to PIE executables |
83 |
|
84 |
and I think the textrels in the intermediate files occur when starting |
85 |
from a vanilla compiler, where libiberty.a is built normally (i.e. not |
86 |
PIE or PIC) in the first pass. Possibly it's also affected by |
87 |
configure thinking the compiler generates PIC by default. |
88 |
|
89 |
|
90 |
> > So, to lib*.a archives. These are collections of object files - how |
91 |
> > they should be built depends on what they're going to be used for, |
92 |
> > and the above rules apply in the same way. In the vast majority of |
93 |
> > cases, whenever someone is linking lib*.a archives into something, |
94 |
> > it's into static binaries as the lib*.a is the static equivalent of |
95 |
> > lib*.so. For these cases, we should have normal (no-PIE) objects. |
96 |
> > |
97 |
> > The cases internal to gcc/glibc are exceptions, in that the |
98 |
> > archives are used to build shared libraries (which use the |
99 |
> > lib*_nonshared.a archives which should always be PIC anyway) and |
100 |
> > those executables - which if we want them to be PIE of course need |
101 |
> > PIE objects. I think a better way to approach this sort of case is |
102 |
> > to modify the build process explicitly to build PIE objects where |
103 |
> > needed, rather than using the altered defaults. |
104 |
> |
105 |
> there are many exceptions, but you do not see them with a glibc/gnu |
106 |
> system. On an uClibc hardened system, if configure fails to detect |
107 |
> correctly the system (needing gnuconfig-update/libtoolize), it will |
108 |
> probably build only lib*.a instead of both lib*.so/lib*.a, and the |
109 |
> next app compiled against lib*.a will have text relocations. |
110 |
|
111 |
I was not aware of that. I would have expected embedded systems to be |
112 |
keen on shared libraries, as they reduce physical memory requirements. |
113 |
Would it be better to have autotools working properly with uclibc? How |
114 |
many packages are we talking about? Would it be reasonable to suggest |
115 |
they be modified to build shared libraries properly (perhaps by |
116 |
directing configure explicitly)? |
117 |
|
118 |
> > > > Strictly speaking, on a hardened system, the -vanilla and |
119 |
> > > > -hardenednopie compiler cannot be guaranteed to generate working |
120 |
> > > > executables - indeed it creates garbage on sparc (x86 seems to |
121 |
> > > > be more forgiving; you can mix PIE objects into a non-PIE |
122 |
> > > > executable and they appear to work). |
123 |
> > > |
124 |
> > > because lib*.a has to be PIC. |
125 |
> > |
126 |
> > Like I say, whether they should be normal, PIC or PIE depends on |
127 |
> > what they're used for - and in general you just don't know. The |
128 |
> > most common use for lib*.a files from the system (/usr/lib etc) is |
129 |
> > to build static binaries. |
130 |
> > |
131 |
> > Consider also the state of the crt*.o objects - on existing hardened |
132 |
> > systems crtbegin.o and friends are built -fPIE. This makes the |
133 |
> |
134 |
> no, crt*S.o are compiled -fPIC at least on linux, see |
135 |
> gcc/config/t-linux CRTSTUFF_T_CFLAGS_S, only those without S are |
136 |
> compiled -fPIE (if gcc defaults to hardened and ... and ..., |
137 |
> depending on the version of the piepatches) |
138 |
|
139 |
Yes. It was just the non-S versions I was talking about (crtbegin.o, |
140 |
crtend.o and friends, crt1.o from libc). |
141 |
|
142 |
> > switching of startfile/endfile in the specs achieve almost nothing |
143 |
> > - on x86, crtend.o and crtendS.o are identical, and |
144 |
> > crtbegin.o/crtbeginS.o are almost the same. Have we really |
145 |
> > analysed the source for those objects, to verify that building them |
146 |
> > -fPIE gives sensible results? I suspect not. |
147 |
> |
148 |
> maybe we should add -fno-PIE to crtbegin.o/crtend.o/crtbeginT.o to |
149 |
> guard against the above case. |
150 |
|
151 |
I did try that, also building crt1.o (libc) with -fno-PIE. The |
152 |
modifications to the toolchain build files got more and more involved, |
153 |
which I really want to avoid. In addition, I suspect that will break |
154 |
your "PIE/static" binaries; where perhaps it would be better to use |
155 |
crt*S.o/Scrt1.o. |
156 |
|
157 |
> > > > I'm working on a sane solution to this problem using ABIs, but |
158 |
> > > > it's quite involved, and it's quite a departure from what we |
159 |
> > > > currently do. Once I have my thoughts clear, I'll post a |
160 |
> > > > proposal. |
161 |
> > > > |
162 |
> > > > For the moment, however, we can continue as we did before, but |
163 |
> > > > highlight that -vanilla and -hardenednopie may not generate |
164 |
> > > > working executables. Mostly this affects bootloaders, and |
165 |
> > > > things like static busybox. |
166 |
> > > |
167 |
> > > Wondering why you mention static binaries, |
168 |
> > |
169 |
> > Static binaries should not be PIE - the two concepts don't mix. It |
170 |
> > doesn't make sense to build an ET_EXEC executable (which is what |
171 |
> > static executables are) with PIE code. |
172 |
> |
173 |
> sadly, when compiling we do not know if the object will go into |
174 |
> static/ET_EXEC/ET_DYN, else we could handle that (we handle only the |
175 |
> case if the final binary is compiled and linked in one step) |
176 |
|
177 |
Yep. The only way I can think of to deal with that would be a |
178 |
normal/PIE multilib setup. For glibc systems it is probably not worth |
179 |
the trouble (since we rarely use the lib*.a archives anyway). For |
180 |
uclibc, it would depend how much breakage there is in building shared |
181 |
libraries. |
182 |
|
183 |
> > > I have no problem on a |
184 |
> > > clean hardened box with static binaries, |
185 |
> > |
186 |
> > What you have aren't really static binaries - they're ET_EXECs with |
187 |
> > PIE objects inside. This kinda works on x86, but on sparc it just |
188 |
> > segfaults on startup (due to the contents of crt*.o). |
189 |
> |
190 |
> I know ppc/arm does not have any problem with it (mips is out of |
191 |
> question because it is always PIC except the kernel) |
192 |
> |
193 |
> give fno-PIE a try for those, maybe it solves the issue. |
194 |
|
195 |
I did try that, I think, but without any success. |
196 |
|
197 |
|
198 |
> > > even if the lib*.a are PIC |
199 |
> > > compiled (mine are for sure, and most of you have it too, if an |
200 |
> > > app is using autotools and running ./configure shows that the |
201 |
> > > system supports shared libraries and for "dependant libraries" it |
202 |
> > > says "pass_all"), I though agree that it is overkill for static |
203 |
> > > binaries to use libraries that were PIC compiled. |
204 |
> > |
205 |
> > The problem with static binaries is that they're not correct on all |
206 |
> > platforms, when built with PIE objects. sparc in particular |
207 |
> > segfaults. It does create executables that run on x86, but they're |
208 |
> > a bizarre PIE/ET_EXEC hybrid that makes little sense. |
209 |
> |
210 |
> sparc or sparc64 or both? have you compared assembler output? does it |
211 |
> make a difference if you provide -K PIC to the assembler or not? |
212 |
|
213 |
sparc64 (sparcv9). The problem was symbols not being resolved |
214 |
properly, iirc. I don't remember exactly what I tried, now - I tried |
215 |
many things, although not -K PIC (I would assume that would be passed |
216 |
to the assembler when building -fPIE or -fPIC). |
217 |
|
218 |
> |
219 |
> Peter |
220 |
> |
221 |
> > What I've done for now, and am proposing we enter into the tree, is |
222 |
> > to build gcc itself (and glibc) non-PIE. This means the crt files |
223 |
> > are built correctly, also libc.a and the gcc lib*.a's are non-PIE |
224 |
> > and suitable for properly static binaries. |
225 |
> > |
226 |
> > This is still not entirely satisfactory; in a perfect world we'd |
227 |
> > have lib*.a available both ET_EXEC and PIE. The only half-sensible |
228 |
> > way I can think of to do that, would be to set things up like a |
229 |
> > multilib system. However until portage supports multilib |
230 |
> > (http://dev.gentoo.org/~kanaka/auto-multilib/ would be my preferred |
231 |
> > approach) I don't think it's worth the trouble. |
232 |
> > |
233 |
> > |
234 |
> |
235 |
|
236 |
|
237 |
-- |
238 |
Kevin F. Quinn |