]> git.ipfire.org Git - people/arne_f/ipfire-3.x.git/blob - glibc/patches/glibc-2.10.1-hardened-inittls-nosysenter.patch
Change file layout of the makefiles.
[people/arne_f/ipfire-3.x.git] / glibc / patches / glibc-2.10.1-hardened-inittls-nosysenter.patch
1 When building glibc PIE (which is not something upstream support),
2 several modifications are necessary to the glibc build process.
3
4 First, any syscalls in PIEs must be of the PIC variant, otherwise
5 textrels ensue. Then, any syscalls made before the initialisation
6 of the TLS will fail on i386, as the sysenter variant on i386 uses
7 the TLS, giving rise to a chicken-and-egg situation. This patch
8 defines a PIC syscall variant that doesn't use sysenter, even when the sysenter
9 version is normally used, and uses the non-sysenter version for the brk
10 syscall that is performed by the TLS initialisation. Further, the TLS
11 initialisation is moved in this case prior to the initialisation of
12 dl_osversion, as that requires further syscalls.
13
14 csu/libc-start.c: Move initial TLS initialization to before the
15 initialisation of dl_osversion, when INTERNAL_SYSCALL_NOSYSENTER is defined
16
17 csu/libc-tls.c: Use the no-sysenter version of sbrk when
18 INTERNAL_SYSCALL_NOSYSENTER is defined.
19
20 misc/sbrk.c: Define a no-sysenter version of sbrk, using the no-sysenter
21 version of brk - if INTERNAL_SYSCALL_NOSYSENTER is defined.
22
23 misc/brk.c: Define a no-sysenter version of brk if
24 INTERNAL_SYSCALL_NOSYSENTER is defined.
25
26 sysdeps/unix/sysv/linux/i386/sysdep.h: Define INTERNAL_SYSCALL_NOSYSENTER
27 Make INTERNAL_SYSCALL always use the PIC variant, even if not SHARED.
28
29 Patch by Kevin F. Quinn <kevquinn@gentoo.org>
30
31 --- glibc-2.10.1/csu/libc-start.c
32 +++ glibc-2.10.1/csu/libc-start.c
33 @@ -28,6 +28,7 @@
34 extern int __libc_multiple_libcs;
35
36 #include <tls.h>
37 +#include <sysdep.h>
38 #ifndef SHARED
39 # include <dl-osinfo.h>
40 extern void __pthread_initialize_minimal (void);
41 @@ -129,6 +130,11 @@
42 # endif
43 _dl_aux_init (auxvec);
44 # endif
45 +# ifdef INTERNAL_SYSCALL_NOSYSENTER
46 + /* Do the initial TLS initialization before _dl_osversion,
47 + since the latter uses the uname syscall. */
48 + __pthread_initialize_minimal ();
49 +# endif
50 # ifdef DL_SYSDEP_OSCHECK
51 if (!__libc_multiple_libcs)
52 {
53 @@ -138,10 +144,12 @@
54 }
55 # endif
56
57 +# ifndef INTERNAL_SYSCALL_NOSYSENTER
58 /* Initialize the thread library at least a bit since the libgcc
59 functions are using thread functions if these are available and
60 we need to setup errno. */
61 __pthread_initialize_minimal ();
62 +# endif
63
64 /* Set up the stack checker's canary. */
65 uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
66 --- glibc-2.10.1/csu/libc-tls.c
67 +++ glibc-2.10.1/csu/libc-tls.c
68 @@ -23,6 +23,7 @@
69 #include <unistd.h>
70 #include <stdio.h>
71 #include <sys/param.h>
72 +#include <sysdep.h>
73
74
75 #ifdef SHARED
76 @@ -29,6 +30,9 @@
77 #error makefile bug, this file is for static only
78 #endif
79
80 +#ifdef INTERNAL_SYSCALL_NOSYSENTER
81 +extern void *__sbrk_nosysenter (intptr_t __delta);
82 +#endif
83 extern ElfW(Phdr) *_dl_phdr;
84 extern size_t _dl_phnum;
85
86 @@ -141,14 +145,26 @@
87
88 The initialized value of _dl_tls_static_size is provided by dl-open.c
89 to request some surplus that permits dynamic loading of modules with
90 - IE-model TLS. */
91 + IE-model TLS.
92 +
93 + Where the normal sbrk would use a syscall that needs the TLS (i386)
94 + use the special non-sysenter version instead. */
95 #if TLS_TCB_AT_TP
96 tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
97 +# ifdef INTERNAL_SYSCALL_NOSYSENTER
98 + tlsblock = __sbrk_nosysenter (tcb_offset + tcbsize + max_align);
99 +# else
100 tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
101 +# endif
102 #elif TLS_DTV_AT_TP
103 tcb_offset = roundup (tcbsize, align ?: 1);
104 +# ifdef INTERNAL_SYSCALL_NOSYSENTER
105 + tlsblock = __sbrk_nosysenter (tcb_offset + memsz + max_align
106 + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
107 +# else
108 tlsblock = __sbrk (tcb_offset + memsz + max_align
109 + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
110 +# endif
111 tlsblock += TLS_PRE_TCB_SIZE;
112 #else
113 /* In case a model with a different layout for the TCB and DTV
114 --- glibc-2.10.1/misc/sbrk.c
115 +++ glibc-2.10.1/misc/sbrk.c
116 @@ -18,6 +18,7 @@
117
118 #include <stdint.h>
119 #include <unistd.h>
120 +#include <sysdep.h>
121
122 /* Defined in brk.c. */
123 extern void *__curbrk;
124 @@ -29,6 +30,35 @@
125 /* Extend the process's data space by INCREMENT.
126 If INCREMENT is negative, shrink data space by - INCREMENT.
127 Return start of new space allocated, or -1 for errors. */
128 +#ifdef INTERNAL_SYSCALL_NOSYSENTER
129 +/* This version is used by csu/libc-tls.c whem initialising the TLS
130 + if the SYSENTER version requires the TLS (which it does on i386).
131 + Obviously using the TLS before it is initialised is broken. */
132 +extern int __brk_nosysenter (void *addr);
133 +void *
134 +__sbrk_nosysenter (intptr_t increment)
135 +{
136 + void *oldbrk;
137 +
138 + /* If this is not part of the dynamic library or the library is used
139 + via dynamic loading in a statically linked program update
140 + __curbrk from the kernel's brk value. That way two separate
141 + instances of __brk and __sbrk can share the heap, returning
142 + interleaved pieces of it. */
143 + if (__curbrk == NULL || __libc_multiple_libcs)
144 + if (__brk_nosysenter (0) < 0) /* Initialize the break. */
145 + return (void *) -1;
146 +
147 + if (increment == 0)
148 + return __curbrk;
149 +
150 + oldbrk = __curbrk;
151 + if (__brk_nosysenter (oldbrk + increment) < 0)
152 + return (void *) -1;
153 +
154 + return oldbrk;
155 +}
156 +#endif
157 void *
158 __sbrk (intptr_t increment)
159 {
160 --- glibc-2.10.1/sysdeps/unix/sysv/linux/i386/brk.c
161 +++ glibc-2.10.1/sysdeps/unix/sysv/linux/i386/brk.c
162 @@ -31,6 +31,30 @@
163 linker. */
164 weak_alias (__curbrk, ___brk_addr)
165
166 +#ifdef INTERNAL_SYSCALL_NOSYSENTER
167 +/* This version is used by csu/libc-tls.c whem initialising the TLS
168 + * if the SYSENTER version requires the TLS (which it does on i386).
169 + * Obviously using the TLS before it is initialised is broken. */
170 +int
171 +__brk_nosysenter (void *addr)
172 +{
173 + void *__unbounded newbrk;
174 +
175 + INTERNAL_SYSCALL_DECL (err);
176 + newbrk = (void *__unbounded) INTERNAL_SYSCALL_NOSYSENTER (brk, err, 1,
177 + __ptrvalue (addr));
178 +
179 + __curbrk = newbrk;
180 +
181 + if (newbrk < addr)
182 + {
183 + __set_errno (ENOMEM);
184 + return -1;
185 + }
186 +
187 + return 0;
188 +}
189 +#endif
190 int
191 __brk (void *addr)
192 {
193 --- glibc-2.10.1/sysdeps/unix/sysv/linux/i386/sysdep.h
194 +++ glibc-2.10.1/sysdeps/unix/sysv/linux/i386/sysdep.h
195 @@ -187,7 +187,7 @@
196 /* The original calling convention for system calls on Linux/i386 is
197 to use int $0x80. */
198 #ifdef I386_USE_SYSENTER
199 -# ifdef SHARED
200 +# if defined SHARED || defined __PIC__
201 # define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
202 # else
203 # define ENTER_KERNEL call *_dl_sysinfo
204 @@ -358,7 +358,7 @@
205 possible to use more than four parameters. */
206 #undef INTERNAL_SYSCALL
207 #ifdef I386_USE_SYSENTER
208 -# ifdef SHARED
209 +# if defined SHARED || defined __PIC__
210 # define INTERNAL_SYSCALL(name, err, nr, args...) \
211 ({ \
212 register unsigned int resultvar; \
213 @@ -384,6 +384,18 @@
214 : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \
215 ASMFMT_##nr(args) : "memory", "cc"); \
216 (int) resultvar; })
217 +# define INTERNAL_SYSCALL_NOSYSENTER(name, err, nr, args...) \
218 + ({ \
219 + register unsigned int resultvar; \
220 + EXTRAVAR_##nr \
221 + asm volatile ( \
222 + LOADARGS_NOSYSENTER_##nr \
223 + "movl %1, %%eax\n\t" \
224 + "int $0x80\n\t" \
225 + RESTOREARGS_NOSYSENTER_##nr \
226 + : "=a" (resultvar) \
227 + : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \
228 + (int) resultvar; })
229 # else
230 # define INTERNAL_SYSCALL(name, err, nr, args...) \
231 ({ \
232 @@ -447,12 +459,20 @@
233
234 #define LOADARGS_0
235 #ifdef __PIC__
236 -# if defined I386_USE_SYSENTER && defined SHARED
237 +# if defined I386_USE_SYSENTER && ( defined SHARED || defined __PIC__ )
238 # define LOADARGS_1 \
239 "bpushl .L__X'%k3, %k3\n\t"
240 # define LOADARGS_5 \
241 "movl %%ebx, %4\n\t" \
242 "movl %3, %%ebx\n\t"
243 +# define LOADARGS_NOSYSENTER_1 \
244 + "bpushl .L__X'%k2, %k2\n\t"
245 +# define LOADARGS_NOSYSENTER_2 LOADARGS_NOSYSENTER_1
246 +# define LOADARGS_NOSYSENTER_3 LOADARGS_3
247 +# define LOADARGS_NOSYSENTER_4 LOADARGS_3
248 +# define LOADARGS_NOSYSENTER_5 \
249 + "movl %%ebx, %3\n\t" \
250 + "movl %2, %%ebx\n\t"
251 # else
252 # define LOADARGS_1 \
253 "bpushl .L__X'%k2, %k2\n\t"
254 @@ -474,11 +495,18 @@
255
256 #define RESTOREARGS_0
257 #ifdef __PIC__
258 -# if defined I386_USE_SYSENTER && defined SHARED
259 +# if defined I386_USE_SYSENTER && ( defined SHARED || defined __PIC__ )
260 # define RESTOREARGS_1 \
261 "bpopl .L__X'%k3, %k3\n\t"
262 # define RESTOREARGS_5 \
263 "movl %4, %%ebx"
264 +# define RESTOREARGS_NOSYSENTER_1 \
265 + "bpopl .L__X'%k2, %k2\n\t"
266 +# define RESTOREARGS_NOSYSENTER_2 RESTOREARGS_NOSYSENTER_1
267 +# define RESTOREARGS_NOSYSENTER_3 RESTOREARGS_3
268 +# define RESTOREARGS_NOSYSENTER_4 RESTOREARGS_3
269 +# define RESTOREARGS_NOSYSENTER_5 \
270 + "movl %3, %%ebx"
271 # else
272 # define RESTOREARGS_1 \
273 "bpopl .L__X'%k2, %k2\n\t"