etc: Enable a tty for a serial port by default.
[dragora.git] / patches / musl / branch-updates.diff
blob850ff7254b4eccf2ca037bd1b0c2f662142e224d
1 diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h
2 index a877b2cf..624e992e 100644
3 --- a/arch/arm/syscall_arch.h
4 +++ b/arch/arm/syscall_arch.h
5 @@ -101,3 +101,10 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
6 #define SYSCALL_FADVISE_6_ARG
8 #define SYSCALL_IPC_BROKEN_MODE
10 +#define VDSO_USEFUL
11 +#define VDSO_CGT32_SYM "__vdso_clock_gettime"
12 +#define VDSO_CGT32_VER "LINUX_2.6"
13 +#define VDSO_CGT_SYM "__vdso_clock_gettime64"
14 +#define VDSO_CGT_VER "LINUX_2.6"
15 +#define VDSO_CGT_WORKAROUND 1
16 diff --git a/compat/time32/__xstat.c b/compat/time32/__xstat.c
17 index acfbd3cc..e52b5deb 100644
18 --- a/compat/time32/__xstat.c
19 +++ b/compat/time32/__xstat.c
20 @@ -3,22 +3,22 @@
22 struct stat32;
24 -int __fxstat64(int ver, int fd, struct stat32 *buf)
25 +int __fxstat(int ver, int fd, struct stat32 *buf)
27 return __fstat_time32(fd, buf);
30 -int __fxstatat64(int ver, int fd, const char *path, struct stat32 *buf, int flag)
31 +int __fxstatat(int ver, int fd, const char *path, struct stat32 *buf, int flag)
33 return __fstatat_time32(fd, path, buf, flag);
36 -int __lxstat64(int ver, const char *path, struct stat32 *buf)
37 +int __lxstat(int ver, const char *path, struct stat32 *buf)
39 return __lstat_time32(path, buf);
42 -int __xstat64(int ver, const char *path, struct stat32 *buf)
43 +int __xstat(int ver, const char *path, struct stat32 *buf)
45 return __stat_time32(path, buf);
47 diff --git a/compat/time32/aio_suspend_time32.c b/compat/time32/aio_suspend_time32.c
48 index ed5119bd..d99cb651 100644
49 --- a/compat/time32/aio_suspend_time32.c
50 +++ b/compat/time32/aio_suspend_time32.c
51 @@ -7,5 +7,3 @@ int __aio_suspend_time32(const struct aiocb *const cbs[], int cnt, const struct
52 return aio_suspend(cbs, cnt, ts32 ? (&(struct timespec){
53 .tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
56 -weak_alias(aio_suspend, aio_suspend64);
57 diff --git a/compat/time32/fstat_time32.c b/compat/time32/fstat_time32.c
58 index 3e084398..e5d52022 100644
59 --- a/compat/time32/fstat_time32.c
60 +++ b/compat/time32/fstat_time32.c
61 @@ -13,5 +13,3 @@ int __fstat_time32(int fd, struct stat32 *restrict st32)
62 if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
63 return r;
66 -weak_alias(fstat, fstat64);
67 diff --git a/compat/time32/fstatat_time32.c b/compat/time32/fstatat_time32.c
68 index 85dcb008..31d42e63 100644
69 --- a/compat/time32/fstatat_time32.c
70 +++ b/compat/time32/fstatat_time32.c
71 @@ -13,5 +13,3 @@ int __fstatat_time32(int fd, const char *restrict path, struct stat32 *restrict
72 if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
73 return r;
76 -weak_alias(fstatat, fstatat64);
77 diff --git a/compat/time32/lstat_time32.c b/compat/time32/lstat_time32.c
78 index c1257a14..28cb5a0b 100644
79 --- a/compat/time32/lstat_time32.c
80 +++ b/compat/time32/lstat_time32.c
81 @@ -13,5 +13,3 @@ int __lstat_time32(const char *restrict path, struct stat32 *restrict st32)
82 if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
83 return r;
86 -weak_alias(lstat, lstat64);
87 diff --git a/compat/time32/stat_time32.c b/compat/time32/stat_time32.c
88 index 8c6121da..b154b0f9 100644
89 --- a/compat/time32/stat_time32.c
90 +++ b/compat/time32/stat_time32.c
91 @@ -13,5 +13,3 @@ int __stat_time32(const char *restrict path, struct stat32 *restrict st32)
92 if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
93 return r;
96 -weak_alias(stat, stat64);
97 diff --git a/configure b/configure
98 index ca5cbc0b..853bf05e 100755
99 --- a/configure
100 +++ b/configure
101 @@ -353,6 +353,14 @@ tryflag CFLAGS_C99FSE -fexcess-precision=standard \
102 || { test "$ARCH" = i386 && tryflag CFLAGS_C99FSE -ffloat-store ; }
103 tryflag CFLAGS_C99FSE -frounding-math
106 +# Semantically we want to insist that our sources follow the
107 +# C rules for type-based aliasing, but most if not all real-world
108 +# compilers are known or suspected to have critical bugs in their
109 +# type-based aliasing analysis. See for example GCC bug 107107.
111 +tryflag CFLAGS_C99FSE -fno-strict-aliasing
114 # We may use the may_alias attribute if __GNUC__ is defined, so
115 # if the compiler defines __GNUC__ but does not provide it,
116 @@ -723,11 +731,6 @@ fi
117 test "$SUBARCH" \
118 && printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH"
120 -case "$ARCH$SUBARCH" in
121 -arm) ASMSUBARCH=el ;;
122 -*) ASMSUBARCH=$SUBARCH ;;
123 -esac
126 # Some archs (powerpc) have different possible long double formats
127 # that the compiler can be configured for. The logic for whether this
128 diff --git a/include/aio.h b/include/aio.h
129 index 453c41b7..a938fcad 100644
130 --- a/include/aio.h
131 +++ b/include/aio.h
132 @@ -49,7 +49,7 @@ int aio_fsync(int, struct aiocb *);
134 int lio_listio(int, struct aiocb *__restrict const *__restrict, int, struct sigevent *__restrict);
136 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
137 +#if defined(_LARGEFILE64_SOURCE)
138 #define aiocb64 aiocb
139 #define aio_read64 aio_read
140 #define aio_write64 aio_write
141 diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
142 index 581925a4..9c1327a1 100644
143 --- a/include/arpa/nameser.h
144 +++ b/include/arpa/nameser.h
145 @@ -188,6 +188,36 @@ typedef enum __ns_type {
146 ns_t_sink = 40,
147 ns_t_opt = 41,
148 ns_t_apl = 42,
149 + ns_t_ds = 43,
150 + ns_t_sshfp = 44,
151 + ns_t_ipseckey = 45,
152 + ns_t_rrsig = 46,
153 + ns_t_nsec = 47,
154 + ns_t_dnskey = 48,
155 + ns_t_dhcid = 49,
156 + ns_t_nsec3 = 50,
157 + ns_t_nsec3param = 51,
158 + ns_t_tlsa = 52,
159 + ns_t_smimea = 53,
160 + ns_t_hip = 55,
161 + ns_t_ninfo = 56,
162 + ns_t_rkey = 57,
163 + ns_t_talink = 58,
164 + ns_t_cds = 59,
165 + ns_t_cdnskey = 60,
166 + ns_t_openpgpkey = 61,
167 + ns_t_csync = 62,
168 + ns_t_spf = 99,
169 + ns_t_uinfo = 100,
170 + ns_t_uid = 101,
171 + ns_t_gid = 102,
172 + ns_t_unspec = 103,
173 + ns_t_nid = 104,
174 + ns_t_l32 = 105,
175 + ns_t_l64 = 106,
176 + ns_t_lp = 107,
177 + ns_t_eui48 = 108,
178 + ns_t_eui64 = 109,
179 ns_t_tkey = 249,
180 ns_t_tsig = 250,
181 ns_t_ixfr = 251,
182 @@ -196,6 +226,11 @@ typedef enum __ns_type {
183 ns_t_maila = 254,
184 ns_t_any = 255,
185 ns_t_zxfr = 256,
186 + ns_t_uri = 256,
187 + ns_t_caa = 257,
188 + ns_t_avc = 258,
189 + ns_t_ta = 32768,
190 + ns_t_dlv = 32769,
191 ns_t_max = 65536
192 } ns_type;
194 @@ -430,12 +465,48 @@ typedef struct {
195 #define T_NAPTR ns_t_naptr
196 #define T_A6 ns_t_a6
197 #define T_DNAME ns_t_dname
198 +#define T_DS ns_t_ds
199 +#define T_SSHFP ns_t_sshfp
200 +#define T_IPSECKEY ns_t_ipseckey
201 +#define T_RRSIG ns_t_rrsig
202 +#define T_NSEC ns_t_nsec
203 +#define T_DNSKEY ns_t_dnskey
204 +#define T_DHCID ns_t_dhcid
205 +#define T_NSEC3 ns_t_nsec3
206 +#define T_NSEC3PARAM ns_t_nsec3param
207 +#define T_TLSA ns_t_tlsa
208 +#define T_SMIMEA ns_t_smimea
209 +#define T_HIP ns_t_hip
210 +#define T_NINFO ns_t_ninfo
211 +#define T_RKEY ns_t_rkey
212 +#define T_TALINK ns_t_talink
213 +#define T_CDS ns_t_cds
214 +#define T_CDNSKEY ns_t_cdnskey
215 +#define T_OPENPGPKEY ns_t_openpgpkey
216 +#define T_CSYNC ns_t_csync
217 +#define T_SPF ns_t_spf
218 +#define T_UINFO ns_t_uinfo
219 +#define T_UID ns_t_uid
220 +#define T_GID ns_t_gid
221 +#define T_UNSPEC ns_t_unspec
222 +#define T_NID ns_t_nid
223 +#define T_L32 ns_t_l32
224 +#define T_L64 ns_t_l64
225 +#define T_LP ns_t_lp
226 +#define T_EUI48 ns_t_eui48
227 +#define T_EUI64 ns_t_eui64
228 +#define T_TKEY ns_t_tkey
229 #define T_TSIG ns_t_tsig
230 #define T_IXFR ns_t_ixfr
231 #define T_AXFR ns_t_axfr
232 #define T_MAILB ns_t_mailb
233 #define T_MAILA ns_t_maila
234 #define T_ANY ns_t_any
235 +#define T_URI ns_t_uri
236 +#define T_CAA ns_t_caa
237 +#define T_AVC ns_t_avc
238 +#define T_TA ns_t_ta
239 +#define T_DLV ns_t_dlv
241 #define C_IN ns_c_in
242 #define C_CHAOS ns_c_chaos
243 diff --git a/include/dirent.h b/include/dirent.h
244 index 650ecf64..2d8fffb2 100644
245 --- a/include/dirent.h
246 +++ b/include/dirent.h
247 @@ -56,7 +56,7 @@ int getdents(int, struct dirent *, size_t);
248 int versionsort(const struct dirent **, const struct dirent **);
249 #endif
251 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
252 +#if defined(_LARGEFILE64_SOURCE)
253 #define dirent64 dirent
254 #define readdir64 readdir
255 #define readdir64_r readdir_r
256 diff --git a/include/elf.h b/include/elf.h
257 index 86e2f0bb..9e980a29 100644
258 --- a/include/elf.h
259 +++ b/include/elf.h
260 @@ -385,7 +385,8 @@ typedef struct {
261 #define SHT_PREINIT_ARRAY 16
262 #define SHT_GROUP 17
263 #define SHT_SYMTAB_SHNDX 18
264 -#define SHT_NUM 19
265 +#define SHT_RELR 19
266 +#define SHT_NUM 20
267 #define SHT_LOOS 0x60000000
268 #define SHT_GNU_ATTRIBUTES 0x6ffffff5
269 #define SHT_GNU_HASH 0x6ffffff6
270 @@ -754,7 +755,10 @@ typedef struct {
271 #define DT_PREINIT_ARRAY 32
272 #define DT_PREINIT_ARRAYSZ 33
273 #define DT_SYMTAB_SHNDX 34
274 -#define DT_NUM 35
275 +#define DT_RELRSZ 35
276 +#define DT_RELR 36
277 +#define DT_RELRENT 37
278 +#define DT_NUM 38
279 #define DT_LOOS 0x6000000d
280 #define DT_HIOS 0x6ffff000
281 #define DT_LOPROC 0x70000000
282 diff --git a/include/fcntl.h b/include/fcntl.h
283 index b664cdc4..515f255d 100644
284 --- a/include/fcntl.h
285 +++ b/include/fcntl.h
286 @@ -195,7 +195,7 @@ ssize_t tee(int, int, size_t, unsigned);
287 #define loff_t off_t
288 #endif
290 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
291 +#if defined(_LARGEFILE64_SOURCE)
292 #define F_GETLK64 F_GETLK
293 #define F_SETLK64 F_SETLK
294 #define F_SETLKW64 F_SETLKW
295 diff --git a/include/ftw.h b/include/ftw.h
296 index b15c062a..d0445e8a 100644
297 --- a/include/ftw.h
298 +++ b/include/ftw.h
299 @@ -29,7 +29,7 @@ struct FTW {
300 int ftw(const char *, int (*)(const char *, const struct stat *, int), int);
301 int nftw(const char *, int (*)(const char *, const struct stat *, int, struct FTW *), int, int);
303 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
304 +#if defined(_LARGEFILE64_SOURCE)
305 #define ftw64 ftw
306 #define nftw64 nftw
307 #endif
308 diff --git a/include/glob.h b/include/glob.h
309 index 4a562a20..fed06745 100644
310 --- a/include/glob.h
311 +++ b/include/glob.h
312 @@ -39,7 +39,7 @@ void globfree(glob_t *);
313 #define GLOB_NOMATCH 3
314 #define GLOB_NOSYS 4
316 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
317 +#if defined(_LARGEFILE64_SOURCE)
318 #define glob64 glob
319 #define globfree64 globfree
320 #define glob64_t glob_t
321 diff --git a/include/netdb.h b/include/netdb.h
322 index d096c781..3af065e2 100644
323 --- a/include/netdb.h
324 +++ b/include/netdb.h
325 @@ -44,6 +44,7 @@ struct addrinfo {
326 #define EAI_NONAME -2
327 #define EAI_AGAIN -3
328 #define EAI_FAIL -4
329 +#define EAI_NODATA -5
330 #define EAI_FAMILY -6
331 #define EAI_SOCKTYPE -7
332 #define EAI_SERVICE -8
333 diff --git a/include/stdio.h b/include/stdio.h
334 index d1ed01f0..cb858618 100644
335 --- a/include/stdio.h
336 +++ b/include/stdio.h
337 @@ -205,7 +205,7 @@ typedef struct _IO_cookie_io_functions_t {
338 FILE *fopencookie(void *, const char *, cookie_io_functions_t);
339 #endif
341 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
342 +#if defined(_LARGEFILE64_SOURCE)
343 #define tmpfile64 tmpfile
344 #define fopen64 fopen
345 #define freopen64 freopen
346 diff --git a/include/stdlib.h b/include/stdlib.h
347 index b507ca33..b117a452 100644
348 --- a/include/stdlib.h
349 +++ b/include/stdlib.h
350 @@ -163,7 +163,7 @@ double strtod_l(const char *__restrict, char **__restrict, struct __locale_struc
351 long double strtold_l(const char *__restrict, char **__restrict, struct __locale_struct *);
352 #endif
354 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
355 +#if defined(_LARGEFILE64_SOURCE)
356 #define mkstemp64 mkstemp
357 #define mkostemp64 mkostemp
358 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
359 diff --git a/include/strings.h b/include/strings.h
360 index db0960b4..b7a5ea08 100644
361 --- a/include/strings.h
362 +++ b/include/strings.h
363 @@ -5,6 +5,7 @@
364 extern "C" {
365 #endif
367 +#include <features.h>
369 #define __NEED_size_t
370 #define __NEED_locale_t
371 diff --git a/include/sys/mman.h b/include/sys/mman.h
372 index 80a3baae..3d5d0f9c 100644
373 --- a/include/sys/mman.h
374 +++ b/include/sys/mman.h
375 @@ -141,7 +141,7 @@ int mincore (void *, size_t, unsigned char *);
376 int shm_open (const char *, int, mode_t);
377 int shm_unlink (const char *);
379 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
380 +#if defined(_LARGEFILE64_SOURCE)
381 #define mmap64 mmap
382 #define off64_t off_t
383 #endif
384 diff --git a/include/sys/resource.h b/include/sys/resource.h
385 index 3068328d..e8bfbe1f 100644
386 --- a/include/sys/resource.h
387 +++ b/include/sys/resource.h
388 @@ -95,7 +95,7 @@ int prlimit(pid_t, int, const struct rlimit *, struct rlimit *);
390 #define RLIM_NLIMITS RLIMIT_NLIMITS
392 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
393 +#if defined(_LARGEFILE64_SOURCE)
394 #define RLIM64_INFINITY RLIM_INFINITY
395 #define RLIM64_SAVED_CUR RLIM_SAVED_CUR
396 #define RLIM64_SAVED_MAX RLIM_SAVED_MAX
397 diff --git a/include/sys/sendfile.h b/include/sys/sendfile.h
398 index e7570d8e..253a041b 100644
399 --- a/include/sys/sendfile.h
400 +++ b/include/sys/sendfile.h
401 @@ -10,7 +10,7 @@ extern "C" {
403 ssize_t sendfile(int, int, off_t *, size_t);
405 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
406 +#if defined(_LARGEFILE64_SOURCE)
407 #define sendfile64 sendfile
408 #define off64_t off_t
409 #endif
410 diff --git a/include/sys/stat.h b/include/sys/stat.h
411 index 10d446c4..e6d0049c 100644
412 --- a/include/sys/stat.h
413 +++ b/include/sys/stat.h
414 @@ -98,7 +98,7 @@ int lchmod(const char *, mode_t);
415 #define S_IEXEC S_IXUSR
416 #endif
418 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
419 +#if defined(_LARGEFILE64_SOURCE)
420 #define stat64 stat
421 #define fstat64 fstat
422 #define lstat64 lstat
423 diff --git a/include/sys/statfs.h b/include/sys/statfs.h
424 index 6f4c6230..7a2e11cd 100644
425 --- a/include/sys/statfs.h
426 +++ b/include/sys/statfs.h
427 @@ -18,7 +18,7 @@ typedef struct __fsid_t {
428 int statfs (const char *, struct statfs *);
429 int fstatfs (int, struct statfs *);
431 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
432 +#if defined(_LARGEFILE64_SOURCE)
433 #define statfs64 statfs
434 #define fstatfs64 fstatfs
435 #define fsblkcnt64_t fsblkcnt_t
436 diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h
437 index 793490b6..57a6b806 100644
438 --- a/include/sys/statvfs.h
439 +++ b/include/sys/statvfs.h
440 @@ -42,7 +42,7 @@ int fstatvfs (int, struct statvfs *);
441 #define ST_NODIRATIME 2048
442 #define ST_RELATIME 4096
444 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
445 +#if defined(_LARGEFILE64_SOURCE)
446 #define statvfs64 statvfs
447 #define fstatvfs64 fstatvfs
448 #define fsblkcnt64_t fsblkcnt_t
449 diff --git a/include/sys/types.h b/include/sys/types.h
450 index 0c35541d..3363374f 100644
451 --- a/include/sys/types.h
452 +++ b/include/sys/types.h
453 @@ -71,7 +71,7 @@ typedef unsigned long long u_quad_t;
454 #include <sys/select.h>
455 #endif
457 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
458 +#if defined(_LARGEFILE64_SOURCE)
459 #define blkcnt64_t blkcnt_t
460 #define fsblkcnt64_t fsblkcnt_t
461 #define fsfilcnt64_t fsfilcnt_t
462 diff --git a/include/sys/uio.h b/include/sys/uio.h
463 index 00f73a2f..90e5939e 100644
464 --- a/include/sys/uio.h
465 +++ b/include/sys/uio.h
466 @@ -29,7 +29,7 @@ ssize_t writev (int, const struct iovec *, int);
467 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
468 ssize_t preadv (int, const struct iovec *, int, off_t);
469 ssize_t pwritev (int, const struct iovec *, int, off_t);
470 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
471 +#if defined(_LARGEFILE64_SOURCE)
472 #define preadv64 preadv
473 #define pwritev64 pwritev
474 #define off64_t off_t
475 diff --git a/include/unistd.h b/include/unistd.h
476 index 212263a7..5bc7f798 100644
477 --- a/include/unistd.h
478 +++ b/include/unistd.h
479 @@ -198,7 +198,7 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
480 pid_t gettid(void);
481 #endif
483 -#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
484 +#if defined(_LARGEFILE64_SOURCE)
485 #define lseek64 lseek
486 #define pread64 pread
487 #define pwrite64 pwrite
488 @@ -425,6 +425,8 @@ pid_t gettid(void);
489 #define _SC_XOPEN_STREAMS 246
490 #define _SC_THREAD_ROBUST_PRIO_INHERIT 247
491 #define _SC_THREAD_ROBUST_PRIO_PROTECT 248
492 +#define _SC_MINSIGSTKSZ 249
493 +#define _SC_SIGSTKSZ 250
495 #define _CS_PATH 0
496 #define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1
497 @@ -467,6 +469,8 @@ pid_t gettid(void);
498 #define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS 1147
499 #define _CS_V6_ENV 1148
500 #define _CS_V7_ENV 1149
501 +#define _CS_POSIX_V7_THREADS_CFLAGS 1150
502 +#define _CS_POSIX_V7_THREADS_LDFLAGS 1151
504 #ifdef __cplusplus
506 diff --git a/ldso/dlstart.c b/ldso/dlstart.c
507 index 20d50f2c..259f5e18 100644
508 --- a/ldso/dlstart.c
509 +++ b/ldso/dlstart.c
510 @@ -140,6 +140,21 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
511 size_t *rel_addr = (void *)(base + rel[0]);
512 *rel_addr = base + rel[2];
515 + rel = (void *)(base+dyn[DT_RELR]);
516 + rel_size = dyn[DT_RELRSZ];
517 + size_t *relr_addr = 0;
518 + for (; rel_size; rel++, rel_size-=sizeof(size_t)) {
519 + if ((rel[0]&1) == 0) {
520 + relr_addr = (void *)(base + rel[0]);
521 + *relr_addr++ += base;
522 + } else {
523 + for (size_t i=0, bitmap=rel[0]; bitmap>>=1; i++)
524 + if (bitmap&1)
525 + relr_addr[i] += base;
526 + relr_addr += 8*sizeof(size_t)-1;
529 #endif
531 stage2_func dls2;
532 diff --git a/ldso/dynlink.c b/ldso/dynlink.c
533 index 5b9c8be4..7b47b163 100644
534 --- a/ldso/dynlink.c
535 +++ b/ldso/dynlink.c
536 @@ -29,7 +29,9 @@
537 #define realloc __libc_realloc
538 #define free __libc_free
540 -static void error(const char *, ...);
541 +static void error_impl(const char *, ...);
542 +static void error_noop(const char *, ...);
543 +static void (*error)(const char *, ...) = error_noop;
545 #define MAXP2(a,b) (-(-(a)&-(b)))
546 #define ALIGN(x,y) ((x)+(y)-1 & -(y))
547 @@ -208,7 +210,8 @@ static void decode_vec(size_t *v, size_t *a, size_t cnt)
548 size_t i;
549 for (i=0; i<cnt; i++) a[i] = 0;
550 for (; v[0]; v+=2) if (v[0]-1<cnt-1) {
551 - a[0] |= 1UL<<v[0];
552 + if (v[0] < 8*sizeof(long))
553 + a[0] |= 1UL<<v[0];
554 a[v[0]] = v[1];
557 @@ -334,6 +337,39 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
558 return find_sym2(dso, s, need_def, 0);
561 +static struct symdef get_lfs64(const char *name)
563 + static const char *p, lfs64_list[] =
564 + "aio_cancel\0aio_error\0aio_fsync\0aio_read\0aio_return\0"
565 + "aio_suspend\0aio_write\0alphasort\0creat\0fallocate\0"
566 + "fgetpos\0fopen\0freopen\0fseeko\0fsetpos\0fstat\0"
567 + "fstatat\0fstatfs\0fstatvfs\0ftello\0ftruncate\0ftw\0"
568 + "getdents\0getrlimit\0glob\0globfree\0lio_listio\0"
569 + "lockf\0lseek\0lstat\0mkostemp\0mkostemps\0mkstemp\0"
570 + "mkstemps\0mmap\0nftw\0open\0openat\0posix_fadvise\0"
571 + "posix_fallocate\0pread\0preadv\0prlimit\0pwrite\0"
572 + "pwritev\0readdir\0scandir\0sendfile\0setrlimit\0"
573 + "stat\0statfs\0statvfs\0tmpfile\0truncate\0versionsort\0"
574 + "__fxstat\0__fxstatat\0__lxstat\0__xstat\0";
575 + size_t l;
576 + char buf[16];
577 + for (l=0; name[l]; l++) {
578 + if (l >= sizeof buf) goto nomatch;
579 + buf[l] = name[l];
581 + if (!strcmp(name, "readdir64_r"))
582 + return find_sym(&ldso, "readdir_r", 1);
583 + if (l<2 || name[l-2]!='6' || name[l-1]!='4')
584 + goto nomatch;
585 + buf[l-=2] = 0;
586 + for (p=lfs64_list; *p; p++) {
587 + if (!strcmp(buf, p)) return find_sym(&ldso, buf, 1);
588 + while (*p) p++;
590 +nomatch:
591 + return (struct symdef){ 0 };
594 static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
596 unsigned char *base = dso->base;
597 @@ -387,6 +423,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
598 def = (sym->st_info>>4) == STB_LOCAL
599 ? (struct symdef){ .dso = dso, .sym = sym }
600 : find_sym(ctx, name, type==REL_PLT);
601 + if (!def.sym) def = get_lfs64(name);
602 if (!def.sym && (sym->st_shndx != SHN_UNDEF
603 || sym->st_info>>4 != STB_WEAK)) {
604 if (dso->lazy && (type==REL_PLT || type==REL_GOT)) {
605 @@ -513,6 +550,23 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
609 +static void do_relr_relocs(struct dso *dso, size_t *relr, size_t relr_size)
611 + unsigned char *base = dso->base;
612 + size_t *reloc_addr;
613 + for (; relr_size; relr++, relr_size-=sizeof(size_t))
614 + if ((relr[0]&1) == 0) {
615 + reloc_addr = laddr(dso, relr[0]);
616 + *reloc_addr++ += (size_t)base;
617 + } else {
618 + int i = 0;
619 + for (size_t bitmap=relr[0]; (bitmap>>=1); i++)
620 + if (bitmap&1)
621 + reloc_addr[i] += (size_t)base;
622 + reloc_addr += 8*sizeof(size_t)-1;
626 static void redo_lazy_relocs()
628 struct dso *p = lazy_head, *next;
629 @@ -866,7 +920,7 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
630 case ENOENT:
631 case ENOTDIR:
632 case EACCES:
633 - break;
634 + return 0;
635 default:
636 return -1;
638 @@ -1355,13 +1409,17 @@ static void reloc_all(struct dso *p)
639 2+(dyn[DT_PLTREL]==DT_RELA));
640 do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2);
641 do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3);
643 - if (head != &ldso && p->relro_start != p->relro_end &&
644 - mprotect(laddr(p, p->relro_start), p->relro_end-p->relro_start, PROT_READ)
645 - && errno != ENOSYS) {
646 - error("Error relocating %s: RELRO protection failed: %m",
647 - p->name);
648 - if (runtime) longjmp(*rtld_fail, 1);
649 + if (!DL_FDPIC)
650 + do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]);
652 + if (head != &ldso && p->relro_start != p->relro_end) {
653 + long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start),
654 + p->relro_end-p->relro_start, PROT_READ);
655 + if (ret != 0 && ret != -ENOSYS) {
656 + error("Error relocating %s: RELRO protection failed: %m",
657 + p->name);
658 + if (runtime) longjmp(*rtld_fail, 1);
662 p->relocated = 1;
663 @@ -1756,6 +1814,9 @@ void __dls3(size_t *sp, size_t *auxv)
664 env_preload = getenv("LD_PRELOAD");
667 + /* Activate error handler function */
668 + error = error_impl;
670 /* If the main program was already loaded by the kernel,
671 * AT_PHDR will point to some location other than the dynamic
672 * linker's program headers. */
673 @@ -2345,7 +2406,7 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void
674 return ret;
677 -static void error(const char *fmt, ...)
678 +static void error_impl(const char *fmt, ...)
680 va_list ap;
681 va_start(ap, fmt);
682 @@ -2359,3 +2420,7 @@ static void error(const char *fmt, ...)
683 __dl_vseterr(fmt, ap);
684 va_end(ap);
687 +static void error_noop(const char *fmt, ...)
690 diff --git a/src/aio/aio.c b/src/aio/aio.c
691 index a1a3e791..d7e063bf 100644
692 --- a/src/aio/aio.c
693 +++ b/src/aio/aio.c
694 @@ -82,6 +82,8 @@ static size_t io_thread_stack_size;
696 static struct aio_queue *__aio_get_queue(int fd, int need)
698 + sigset_t allmask, origmask;
699 + int masked = 0;
700 if (fd < 0) {
701 errno = EBADF;
702 return 0;
703 @@ -93,6 +95,9 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
704 if ((!map || !map[a] || !map[a][b] || !map[a][b][c] || !(q=map[a][b][c][d])) && need) {
705 pthread_rwlock_unlock(&maplock);
706 if (fcntl(fd, F_GETFD) < 0) return 0;
707 + sigfillset(&allmask);
708 + masked = 1;
709 + pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
710 pthread_rwlock_wrlock(&maplock);
711 if (!io_thread_stack_size) {
712 unsigned long val = __getauxval(AT_MINSIGSTKSZ);
713 @@ -119,6 +124,7 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
714 if (q) pthread_mutex_lock(&q->lock);
715 out:
716 pthread_rwlock_unlock(&maplock);
717 + if (masked) pthread_sigmask(SIG_SETMASK, &origmask, 0);
718 return q;
721 @@ -401,18 +407,26 @@ void __aio_atfork(int who)
722 if (who<0) {
723 pthread_rwlock_rdlock(&maplock);
724 return;
725 + } else if (!who) {
726 + pthread_rwlock_unlock(&maplock);
727 + return;
729 - if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++)
730 + aio_fd_cnt = 0;
731 + if (pthread_rwlock_tryrdlock(&maplock)) {
732 + /* Obtaining lock may fail if _Fork was called nor via
733 + * fork. In this case, no further aio is possible from
734 + * child and we can just null out map so __aio_close
735 + * does not attempt to do anything. */
736 + map = 0;
737 + return;
739 + if (map) for (int a=0; a<(-1U/2+1)>>24; a++)
740 if (map[a]) for (int b=0; b<256; b++)
741 if (map[a][b]) for (int c=0; c<256; c++)
742 if (map[a][b][c]) for (int d=0; d<256; d++)
743 map[a][b][c][d] = 0;
744 - pthread_rwlock_unlock(&maplock);
745 + /* Re-initialize the rwlock rather than unlocking since there
746 + * may have been more than one reference on it in the parent.
747 + * We are not a lock holder anyway; the thread in the parent was. */
748 + pthread_rwlock_init(&maplock, 0);
751 -weak_alias(aio_cancel, aio_cancel64);
752 -weak_alias(aio_error, aio_error64);
753 -weak_alias(aio_fsync, aio_fsync64);
754 -weak_alias(aio_read, aio_read64);
755 -weak_alias(aio_write, aio_write64);
756 -weak_alias(aio_return, aio_return64);
757 diff --git a/src/aio/aio_suspend.c b/src/aio/aio_suspend.c
758 index 1c1060e3..1f0c9aaa 100644
759 --- a/src/aio/aio_suspend.c
760 +++ b/src/aio/aio_suspend.c
761 @@ -9,7 +9,7 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
763 int i, tid = 0, ret, expect = 0;
764 struct timespec at;
765 - volatile int dummy_fut, *pfut;
766 + volatile int dummy_fut = 0, *pfut;
767 int nzcnt = 0;
768 const struct aiocb *cb = 0;
770 @@ -73,7 +73,3 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
775 -#if !_REDIR_TIME64
776 -weak_alias(aio_suspend, aio_suspend64);
777 -#endif
778 diff --git a/src/aio/lio_listio.c b/src/aio/lio_listio.c
779 index 0799c15d..a672812f 100644
780 --- a/src/aio/lio_listio.c
781 +++ b/src/aio/lio_listio.c
782 @@ -139,5 +139,3 @@ int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, st
784 return 0;
787 -weak_alias(lio_listio, lio_listio64);
788 diff --git a/src/conf/confstr.c b/src/conf/confstr.c
789 index 02cb1aa2..3d417284 100644
790 --- a/src/conf/confstr.c
791 +++ b/src/conf/confstr.c
792 @@ -7,7 +7,7 @@ size_t confstr(int name, char *buf, size_t len)
793 const char *s = "";
794 if (!name) {
795 s = "/bin:/usr/bin";
796 - } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>33U) {
797 + } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>35U) {
798 errno = EINVAL;
799 return 0;
801 diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c
802 index 3baaed32..60d3e745 100644
803 --- a/src/conf/sysconf.c
804 +++ b/src/conf/sysconf.c
805 @@ -4,6 +4,7 @@
806 #include <sys/resource.h>
807 #include <signal.h>
808 #include <sys/sysinfo.h>
809 +#include <sys/auxv.h>
810 #include "syscall.h"
811 #include "libc.h"
813 @@ -19,6 +20,8 @@
814 #define JT_AVPHYS_PAGES JT(9)
815 #define JT_ZERO JT(10)
816 #define JT_DELAYTIMER_MAX JT(11)
817 +#define JT_MINSIGSTKSZ JT(12)
818 +#define JT_SIGSTKSZ JT(13)
820 #define RLIM(x) (-32768|(RLIMIT_ ## x))
822 @@ -165,6 +168,9 @@ long sysconf(int name)
823 [_SC_XOPEN_STREAMS] = JT_ZERO,
824 [_SC_THREAD_ROBUST_PRIO_INHERIT] = -1,
825 [_SC_THREAD_ROBUST_PRIO_PROTECT] = -1,
827 + [_SC_MINSIGSTKSZ] = JT_MINSIGSTKSZ,
828 + [_SC_SIGSTKSZ] = JT_SIGSTKSZ,
831 if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) {
832 @@ -212,6 +218,13 @@ long sysconf(int name)
833 mem *= si.mem_unit;
834 mem /= PAGE_SIZE;
835 return (mem > LONG_MAX) ? LONG_MAX : mem;
836 + case JT_MINSIGSTKSZ & 255:
837 + case JT_SIGSTKSZ & 255: ;
838 + long val = __getauxval(AT_MINSIGSTKSZ);
839 + if (val < MINSIGSTKSZ) val = MINSIGSTKSZ;
840 + if (values[name] == JT_SIGSTKSZ)
841 + val += SIGSTKSZ - MINSIGSTKSZ;
842 + return val;
843 case JT_ZERO & 255:
844 return 0;
846 diff --git a/src/dirent/alphasort.c b/src/dirent/alphasort.c
847 index bee672eb..ab2624e2 100644
848 --- a/src/dirent/alphasort.c
849 +++ b/src/dirent/alphasort.c
850 @@ -5,5 +5,3 @@ int alphasort(const struct dirent **a, const struct dirent **b)
852 return strcoll((*a)->d_name, (*b)->d_name);
855 -weak_alias(alphasort, alphasort64);
856 diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c
857 index 569fc705..5a03b363 100644
858 --- a/src/dirent/readdir.c
859 +++ b/src/dirent/readdir.c
860 @@ -25,5 +25,3 @@ struct dirent *readdir(DIR *dir)
861 dir->tell = de->d_off;
862 return de;
865 -weak_alias(readdir, readdir64);
866 diff --git a/src/dirent/readdir_r.c b/src/dirent/readdir_r.c
867 index e2a818f3..0d5de5f5 100644
868 --- a/src/dirent/readdir_r.c
869 +++ b/src/dirent/readdir_r.c
870 @@ -25,5 +25,3 @@ int readdir_r(DIR *restrict dir, struct dirent *restrict buf, struct dirent **re
871 *result = buf;
872 return 0;
875 -weak_alias(readdir_r, readdir64_r);
876 diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c
877 index 7ee195dd..7456b9b8 100644
878 --- a/src/dirent/scandir.c
879 +++ b/src/dirent/scandir.c
880 @@ -43,5 +43,3 @@ int scandir(const char *path, struct dirent ***res,
881 *res = names;
882 return cnt;
885 -weak_alias(scandir, scandir64);
886 diff --git a/src/dirent/versionsort.c b/src/dirent/versionsort.c
887 index d4c48923..97696105 100644
888 --- a/src/dirent/versionsort.c
889 +++ b/src/dirent/versionsort.c
890 @@ -6,6 +6,3 @@ int versionsort(const struct dirent **a, const struct dirent **b)
892 return strverscmp((*a)->d_name, (*b)->d_name);
895 -#undef versionsort64
896 -weak_alias(versionsort, versionsort64);
897 diff --git a/src/fcntl/creat.c b/src/fcntl/creat.c
898 index 8f8aab64..c9c43910 100644
899 --- a/src/fcntl/creat.c
900 +++ b/src/fcntl/creat.c
901 @@ -4,5 +4,3 @@ int creat(const char *filename, mode_t mode)
903 return open(filename, O_CREAT|O_WRONLY|O_TRUNC, mode);
906 -weak_alias(creat, creat64);
907 diff --git a/src/fcntl/open.c b/src/fcntl/open.c
908 index 1d817a2d..4c3c8275 100644
909 --- a/src/fcntl/open.c
910 +++ b/src/fcntl/open.c
911 @@ -19,5 +19,3 @@ int open(const char *filename, int flags, ...)
913 return __syscall_ret(fd);
916 -weak_alias(open, open64);
917 diff --git a/src/fcntl/openat.c b/src/fcntl/openat.c
918 index ad165ec3..83a9e0d0 100644
919 --- a/src/fcntl/openat.c
920 +++ b/src/fcntl/openat.c
921 @@ -15,5 +15,3 @@ int openat(int fd, const char *filename, int flags, ...)
923 return syscall_cp(SYS_openat, fd, filename, flags|O_LARGEFILE, mode);
926 -weak_alias(openat, openat64);
927 diff --git a/src/fcntl/posix_fadvise.c b/src/fcntl/posix_fadvise.c
928 index 75b8e1ae..07346d21 100644
929 --- a/src/fcntl/posix_fadvise.c
930 +++ b/src/fcntl/posix_fadvise.c
931 @@ -14,5 +14,3 @@ int posix_fadvise(int fd, off_t base, off_t len, int advice)
932 __SYSCALL_LL_E(len), advice);
933 #endif
936 -weak_alias(posix_fadvise, posix_fadvise64);
937 diff --git a/src/fcntl/posix_fallocate.c b/src/fcntl/posix_fallocate.c
938 index c57a24ae..80a65cbf 100644
939 --- a/src/fcntl/posix_fallocate.c
940 +++ b/src/fcntl/posix_fallocate.c
941 @@ -6,5 +6,3 @@ int posix_fallocate(int fd, off_t base, off_t len)
942 return -__syscall(SYS_fallocate, fd, 0, __SYSCALL_LL_E(base),
943 __SYSCALL_LL_E(len));
946 -weak_alias(posix_fallocate, posix_fallocate64);
947 diff --git a/src/include/sys/stat.h b/src/include/sys/stat.h
948 new file mode 100644
949 index 00000000..59339bee
950 --- /dev/null
951 +++ b/src/include/sys/stat.h
952 @@ -0,0 +1,9 @@
953 +#ifndef SYS_STAT_H
954 +#define SYS_STAT_H
956 +#include "../../../include/sys/stat.h"
958 +hidden int __fstat(int, struct stat *);
959 +hidden int __fstatat(int, const char *restrict, struct stat *restrict, int);
961 +#endif
962 diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h
963 index 51c0639f..830354eb 100644
964 --- a/src/internal/dynlink.h
965 +++ b/src/internal/dynlink.h
966 @@ -93,7 +93,7 @@ struct fdpic_dummy_loadmap {
967 #endif
969 #define AUX_CNT 32
970 -#define DYN_CNT 32
971 +#define DYN_CNT 37
973 typedef void (*stage2_func)(unsigned char *, size_t *);
975 diff --git a/src/internal/fork_impl.h b/src/internal/fork_impl.h
976 index 5892c13b..354e733b 100644
977 --- a/src/internal/fork_impl.h
978 +++ b/src/internal/fork_impl.h
979 @@ -2,7 +2,6 @@
981 extern hidden volatile int *const __at_quick_exit_lockptr;
982 extern hidden volatile int *const __atexit_lockptr;
983 -extern hidden volatile int *const __dlerror_lockptr;
984 extern hidden volatile int *const __gettext_lockptr;
985 extern hidden volatile int *const __locale_lockptr;
986 extern hidden volatile int *const __random_lockptr;
987 @@ -17,3 +16,4 @@ extern hidden volatile int *const __vmlock_lockptr;
989 hidden void __malloc_atfork(int);
990 hidden void __ldso_atfork(int);
991 +hidden void __pthread_key_atfork(int);
992 diff --git a/src/internal/syscall.h b/src/internal/syscall.h
993 index d5f294d4..4a446157 100644
994 --- a/src/internal/syscall.h
995 +++ b/src/internal/syscall.h
996 @@ -58,7 +58,7 @@ hidden long __syscall_ret(unsigned long),
997 #define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__)
998 #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__))
1000 -static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, long c, long d, long e, long f)
1001 +static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, syscall_arg_t b, syscall_arg_t c, syscall_arg_t d, syscall_arg_t e, syscall_arg_t f)
1003 long r;
1004 if (cp) r = __syscall_cp(sys, a, b, c, d, e, f);
1005 @@ -71,9 +71,9 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l
1006 return r;
1008 #define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \
1009 - (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f))
1010 + __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
1011 #define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \
1012 - (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f))
1013 + __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
1015 /* fixup legacy 16-bit junk */
1017 @@ -201,43 +201,43 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l
1018 #define SYS_sendfile SYS_sendfile64
1019 #endif
1021 -#ifndef SYS_timer_settime
1022 +#ifdef SYS_timer_settime32
1023 #define SYS_timer_settime SYS_timer_settime32
1024 #endif
1026 -#ifndef SYS_timer_gettime
1027 +#ifdef SYS_timer_gettime32
1028 #define SYS_timer_gettime SYS_timer_gettime32
1029 #endif
1031 -#ifndef SYS_timerfd_settime
1032 +#ifdef SYS_timerfd_settime32
1033 #define SYS_timerfd_settime SYS_timerfd_settime32
1034 #endif
1036 -#ifndef SYS_timerfd_gettime
1037 +#ifdef SYS_timerfd_gettime32
1038 #define SYS_timerfd_gettime SYS_timerfd_gettime32
1039 #endif
1041 -#ifndef SYS_clock_settime
1042 +#ifdef SYS_clock_settime32
1043 #define SYS_clock_settime SYS_clock_settime32
1044 #endif
1046 -#ifndef SYS_clock_gettime
1047 +#ifdef SYS_clock_gettime32
1048 #define SYS_clock_gettime SYS_clock_gettime32
1049 #endif
1051 -#ifndef SYS_clock_getres
1052 +#ifdef SYS_clock_getres_time32
1053 #define SYS_clock_getres SYS_clock_getres_time32
1054 #endif
1056 -#ifndef SYS_clock_nanosleep
1057 +#ifdef SYS_clock_nanosleep_time32
1058 #define SYS_clock_nanosleep SYS_clock_nanosleep_time32
1059 #endif
1061 -#ifndef SYS_gettimeofday
1062 +#ifdef SYS_gettimeofday_time32
1063 #define SYS_gettimeofday SYS_gettimeofday_time32
1064 #endif
1066 -#ifndef SYS_settimeofday
1067 +#ifdef SYS_settimeofday_time32
1068 #define SYS_settimeofday SYS_settimeofday_time32
1069 #endif
1071 diff --git a/src/ldso/dlerror.c b/src/ldso/dlerror.c
1072 index afe59253..dae0f3a9 100644
1073 --- a/src/ldso/dlerror.c
1074 +++ b/src/ldso/dlerror.c
1075 @@ -3,8 +3,7 @@
1076 #include <stdarg.h>
1077 #include "pthread_impl.h"
1078 #include "dynlink.h"
1079 -#include "lock.h"
1080 -#include "fork_impl.h"
1081 +#include "atomic.h"
1083 #define malloc __libc_malloc
1084 #define calloc __libc_calloc
1085 @@ -23,28 +22,31 @@ char *dlerror()
1086 return s;
1089 -static volatile int freebuf_queue_lock[1];
1090 -static void **freebuf_queue;
1091 -volatile int *const __dlerror_lockptr = freebuf_queue_lock;
1092 +/* Atomic singly-linked list, used to store list of thread-local dlerror
1093 + * buffers for deferred free. They cannot be freed at thread exit time
1094 + * because, by the time it's known they can be freed, the exiting thread
1095 + * is in a highly restrictive context where it cannot call (even the
1096 + * libc-internal) free. It also can't take locks; thus the atomic list. */
1098 +static void *volatile freebuf_queue;
1100 void __dl_thread_cleanup(void)
1102 pthread_t self = __pthread_self();
1103 - if (self->dlerror_buf && self->dlerror_buf != (void *)-1) {
1104 - LOCK(freebuf_queue_lock);
1105 - void **p = (void **)self->dlerror_buf;
1106 - *p = freebuf_queue;
1107 - freebuf_queue = p;
1108 - UNLOCK(freebuf_queue_lock);
1110 + if (!self->dlerror_buf || self->dlerror_buf == (void *)-1)
1111 + return;
1112 + void *h;
1113 + do {
1114 + h = freebuf_queue;
1115 + *(void **)self->dlerror_buf = h;
1116 + } while (a_cas_p(&freebuf_queue, h, self->dlerror_buf) != h);
1119 hidden void __dl_vseterr(const char *fmt, va_list ap)
1121 - LOCK(freebuf_queue_lock);
1122 - void **q = freebuf_queue;
1123 - freebuf_queue = 0;
1124 - UNLOCK(freebuf_queue_lock);
1125 + void **q;
1126 + do q = freebuf_queue;
1127 + while (q && a_cas_p(&freebuf_queue, q, 0) != q);
1129 while (q) {
1130 void **p = *q;
1131 diff --git a/src/legacy/ftw.c b/src/legacy/ftw.c
1132 index 506bd29c..e757fc6f 100644
1133 --- a/src/legacy/ftw.c
1134 +++ b/src/legacy/ftw.c
1135 @@ -7,5 +7,3 @@ int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int
1136 * actually undefined, but works on all real-world machines. */
1137 return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS);
1140 -weak_alias(ftw, ftw64);
1141 diff --git a/src/linux/epoll.c b/src/linux/epoll.c
1142 index 93baa814..e56e8f4c 100644
1143 --- a/src/linux/epoll.c
1144 +++ b/src/linux/epoll.c
1145 @@ -5,6 +5,7 @@
1147 int epoll_create(int size)
1149 + if (size<=0) return __syscall_ret(-EINVAL);
1150 return epoll_create1(0);
1153 diff --git a/src/linux/fallocate.c b/src/linux/fallocate.c
1154 index 7d68bc8f..9146350e 100644
1155 --- a/src/linux/fallocate.c
1156 +++ b/src/linux/fallocate.c
1157 @@ -7,6 +7,3 @@ int fallocate(int fd, int mode, off_t base, off_t len)
1158 return syscall(SYS_fallocate, fd, mode, __SYSCALL_LL_E(base),
1159 __SYSCALL_LL_E(len));
1162 -#undef fallocate64
1163 -weak_alias(fallocate, fallocate64);
1164 diff --git a/src/linux/getdents.c b/src/linux/getdents.c
1165 index 796c1e5c..97f76e14 100644
1166 --- a/src/linux/getdents.c
1167 +++ b/src/linux/getdents.c
1168 @@ -8,5 +8,3 @@ int getdents(int fd, struct dirent *buf, size_t len)
1169 if (len>INT_MAX) len = INT_MAX;
1170 return syscall(SYS_getdents, fd, buf, len);
1173 -weak_alias(getdents, getdents64);
1174 diff --git a/src/linux/membarrier.c b/src/linux/membarrier.c
1175 index 343f7360..f64fe7e1 100644
1176 --- a/src/linux/membarrier.c
1177 +++ b/src/linux/membarrier.c
1178 @@ -35,7 +35,7 @@ int __membarrier(int cmd, int flags)
1179 __tl_lock();
1180 sem_init(&barrier_sem, 0, 0);
1181 struct sigaction sa = {
1182 - .sa_flags = SA_RESTART,
1183 + .sa_flags = SA_RESTART | SA_ONSTACK,
1184 .sa_handler = bcast_barrier
1186 memset(&sa.sa_mask, -1, sizeof sa.sa_mask);
1187 diff --git a/src/linux/prlimit.c b/src/linux/prlimit.c
1188 index 3df9ffba..fcf45aab 100644
1189 --- a/src/linux/prlimit.c
1190 +++ b/src/linux/prlimit.c
1191 @@ -21,6 +21,3 @@ int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlim
1193 return r;
1196 -#undef prlimit64
1197 -weak_alias(prlimit, prlimit64);
1198 diff --git a/src/linux/sendfile.c b/src/linux/sendfile.c
1199 index 9afe6dd6..fc1577d3 100644
1200 --- a/src/linux/sendfile.c
1201 +++ b/src/linux/sendfile.c
1202 @@ -5,5 +5,3 @@ ssize_t sendfile(int out_fd, int in_fd, off_t *ofs, size_t count)
1204 return syscall(SYS_sendfile, out_fd, in_fd, ofs, count);
1207 -weak_alias(sendfile, sendfile64);
1208 diff --git a/src/malloc/mallocng/free.c b/src/malloc/mallocng/free.c
1209 index 418a085c..43f32aad 100644
1210 --- a/src/malloc/mallocng/free.c
1211 +++ b/src/malloc/mallocng/free.c
1212 @@ -119,7 +119,7 @@ void free(void *p)
1213 if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) {
1214 unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1));
1215 size_t len = (end-base) & -PGSZ;
1216 - if (len) {
1217 + if (len && USE_MADV_FREE) {
1218 int e = errno;
1219 madvise(base, len, MADV_FREE);
1220 errno = e;
1221 diff --git a/src/malloc/mallocng/glue.h b/src/malloc/mallocng/glue.h
1222 index 151c48b8..77f4c812 100644
1223 --- a/src/malloc/mallocng/glue.h
1224 +++ b/src/malloc/mallocng/glue.h
1225 @@ -24,6 +24,8 @@
1226 #define realloc __libc_realloc
1227 #define free __libc_free
1229 +#define USE_MADV_FREE 0
1231 #if USE_REAL_ASSERT
1232 #include <assert.h>
1233 #else
1234 diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c
1235 index 2ab2f0f4..a5558d81 100644
1236 --- a/src/misc/getrlimit.c
1237 +++ b/src/misc/getrlimit.c
1238 @@ -6,12 +6,13 @@
1240 int getrlimit(int resource, struct rlimit *rlim)
1242 - unsigned long k_rlim[2];
1243 int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim);
1244 if (!ret) {
1245 FIX(rlim->rlim_cur);
1246 FIX(rlim->rlim_max);
1248 +#ifdef SYS_getrlimit
1249 + unsigned long k_rlim[2];
1250 if (!ret || errno != ENOSYS)
1251 return ret;
1252 if (syscall(SYS_getrlimit, resource, k_rlim) < 0)
1253 @@ -21,6 +22,7 @@ int getrlimit(int resource, struct rlimit *rlim)
1254 FIX(rlim->rlim_cur);
1255 FIX(rlim->rlim_max);
1256 return 0;
1257 +#else
1258 + return ret;
1259 +#endif
1262 -weak_alias(getrlimit, getrlimit64);
1263 diff --git a/src/misc/lockf.c b/src/misc/lockf.c
1264 index 16a80bec..0162442b 100644
1265 --- a/src/misc/lockf.c
1266 +++ b/src/misc/lockf.c
1267 @@ -28,5 +28,3 @@ int lockf(int fd, int op, off_t size)
1268 errno = EINVAL;
1269 return -1;
1272 -weak_alias(lockf, lockf64);
1273 diff --git a/src/misc/mntent.c b/src/misc/mntent.c
1274 index eabb8200..d404fbe3 100644
1275 --- a/src/misc/mntent.c
1276 +++ b/src/misc/mntent.c
1277 @@ -2,6 +2,7 @@
1278 #include <string.h>
1279 #include <mntent.h>
1280 #include <errno.h>
1281 +#include <limits.h>
1283 static char *internal_buf;
1284 static size_t internal_bufsize;
1285 @@ -21,7 +22,8 @@ int endmntent(FILE *f)
1287 struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen)
1289 - int cnt, n[8], use_internal = (linebuf == SENTINEL);
1290 + int n[8], use_internal = (linebuf == SENTINEL);
1291 + size_t len, i;
1293 mnt->mnt_freq = 0;
1294 mnt->mnt_passno = 0;
1295 @@ -39,10 +41,14 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle
1296 errno = ERANGE;
1297 return 0;
1299 - cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
1301 + len = strlen(linebuf);
1302 + if (len > INT_MAX) continue;
1303 + for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
1304 + sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
1305 n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
1306 &mnt->mnt_freq, &mnt->mnt_passno);
1307 - } while (cnt < 2 || linebuf[n[0]] == '#');
1308 + } while (linebuf[n[0]] == '#' || n[1]==len);
1310 linebuf[n[1]] = 0;
1311 linebuf[n[3]] = 0;
1312 diff --git a/src/misc/nftw.c b/src/misc/nftw.c
1313 index 8dcff7fe..fcd25a73 100644
1314 --- a/src/misc/nftw.c
1315 +++ b/src/misc/nftw.c
1316 @@ -138,5 +138,3 @@ int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, str
1317 pthread_setcancelstate(cs, 0);
1318 return r;
1321 -weak_alias(nftw, nftw64);
1322 diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c
1323 index 8340aee0..edb413fa 100644
1324 --- a/src/misc/setrlimit.c
1325 +++ b/src/misc/setrlimit.c
1326 @@ -12,12 +12,14 @@ struct ctx {
1327 int err;
1330 +#ifdef SYS_setrlimit
1331 static void do_setrlimit(void *p)
1333 struct ctx *c = p;
1334 if (c->err>0) return;
1335 c->err = -__syscall(SYS_setrlimit, c->res, c->lim);
1337 +#endif
1339 int setrlimit(int resource, const struct rlimit *rlim)
1341 @@ -29,6 +31,7 @@ int setrlimit(int resource, const struct rlimit *rlim)
1342 rlim = &tmp;
1344 int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
1345 +#ifdef SYS_setrlimit
1346 if (ret != -ENOSYS) return __syscall_ret(ret);
1348 struct ctx c = {
1349 @@ -42,6 +45,7 @@ int setrlimit(int resource, const struct rlimit *rlim)
1350 return -1;
1352 return 0;
1353 +#else
1354 + return __syscall_ret(ret);
1355 +#endif
1358 -weak_alias(setrlimit, setrlimit64);
1359 diff --git a/src/mman/mmap.c b/src/mman/mmap.c
1360 index eff88d82..43e5e029 100644
1361 --- a/src/mman/mmap.c
1362 +++ b/src/mman/mmap.c
1363 @@ -37,5 +37,3 @@ void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
1366 weak_alias(__mmap, mmap);
1368 -weak_alias(mmap, mmap64);
1369 diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c
1370 index 9596580e..56b71503 100644
1371 --- a/src/network/gai_strerror.c
1372 +++ b/src/network/gai_strerror.c
1373 @@ -6,7 +6,7 @@ static const char msgs[] =
1374 "Name does not resolve\0"
1375 "Try again\0"
1376 "Non-recoverable error\0"
1377 - "Unknown error\0"
1378 + "Name has no usable address\0"
1379 "Unrecognized address family or invalid length\0"
1380 "Unrecognized socket type\0"
1381 "Unrecognized service\0"
1382 diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c
1383 index efaab306..64ad259a 100644
1384 --- a/src/network/getaddrinfo.c
1385 +++ b/src/network/getaddrinfo.c
1386 @@ -16,6 +16,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
1387 char canon[256], *outcanon;
1388 int nservs, naddrs, nais, canon_len, i, j, k;
1389 int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0;
1390 + int no_family = 0;
1391 struct aibuf *out;
1393 if (!host && !serv) return EAI_NONAME;
1394 @@ -66,9 +67,11 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
1395 pthread_setcancelstate(
1396 PTHREAD_CANCEL_DISABLE, &cs);
1397 int r = connect(s, ta[i], tl[i]);
1398 + int saved_errno = errno;
1399 pthread_setcancelstate(cs, 0);
1400 close(s);
1401 if (!r) continue;
1402 + errno = saved_errno;
1404 switch (errno) {
1405 case EADDRNOTAVAIL:
1406 @@ -80,7 +83,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
1407 default:
1408 return EAI_SYSTEM;
1410 - if (family == tf[i]) return EAI_NONAME;
1411 + if (family == tf[i]) no_family = 1;
1412 family = tf[1-i];
1415 @@ -91,6 +94,8 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
1416 naddrs = __lookup_name(addrs, canon, host, family, flags);
1417 if (naddrs < 0) return naddrs;
1419 + if (no_family) return EAI_NODATA;
1421 nais = nservs * naddrs;
1422 canon_len = strlen(canon);
1423 out = calloc(1, nais * sizeof(*out) + canon_len + 1);
1424 diff --git a/src/network/gethostbyaddr.c b/src/network/gethostbyaddr.c
1425 index 598e2241..c3cacaac 100644
1426 --- a/src/network/gethostbyaddr.c
1427 +++ b/src/network/gethostbyaddr.c
1428 @@ -20,5 +20,5 @@ struct hostent *gethostbyaddr(const void *a, socklen_t l, int af)
1429 err = gethostbyaddr_r(a, l, af, h,
1430 (void *)(h+1), size-sizeof *h, &res, &h_errno);
1431 } while (err == ERANGE);
1432 - return err ? 0 : h;
1433 + return res;
1435 diff --git a/src/network/gethostbyaddr_r.c b/src/network/gethostbyaddr_r.c
1436 index 0f1e61aa..ceaf3935 100644
1437 --- a/src/network/gethostbyaddr_r.c
1438 +++ b/src/network/gethostbyaddr_r.c
1439 @@ -54,9 +54,10 @@ int gethostbyaddr_r(const void *a, socklen_t l, int af,
1440 case EAI_OVERFLOW:
1441 return ERANGE;
1442 default:
1443 - case EAI_MEMORY:
1444 - case EAI_SYSTEM:
1445 case EAI_FAIL:
1446 + *err = NO_RECOVERY;
1447 + return EBADMSG;
1448 + case EAI_SYSTEM:
1449 *err = NO_RECOVERY;
1450 return errno;
1451 case 0:
1452 diff --git a/src/network/gethostbyname2.c b/src/network/gethostbyname2.c
1453 index dc9d6621..bd0da7f8 100644
1454 --- a/src/network/gethostbyname2.c
1455 +++ b/src/network/gethostbyname2.c
1456 @@ -21,5 +21,5 @@ struct hostent *gethostbyname2(const char *name, int af)
1457 err = gethostbyname2_r(name, af, h,
1458 (void *)(h+1), size-sizeof *h, &res, &h_errno);
1459 } while (err == ERANGE);
1460 - return err ? 0 : h;
1461 + return res;
1463 diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c
1464 index fc894877..a5eb67fe 100644
1465 --- a/src/network/gethostbyname2_r.c
1466 +++ b/src/network/gethostbyname2_r.c
1467 @@ -22,7 +22,10 @@ int gethostbyname2_r(const char *name, int af,
1468 if (cnt<0) switch (cnt) {
1469 case EAI_NONAME:
1470 *err = HOST_NOT_FOUND;
1471 - return ENOENT;
1472 + return 0;
1473 + case EAI_NODATA:
1474 + *err = NO_DATA;
1475 + return 0;
1476 case EAI_AGAIN:
1477 *err = TRY_AGAIN;
1478 return EAGAIN;
1479 @@ -30,7 +33,6 @@ int gethostbyname2_r(const char *name, int af,
1480 case EAI_FAIL:
1481 *err = NO_RECOVERY;
1482 return EBADMSG;
1483 - case EAI_MEMORY:
1484 case EAI_SYSTEM:
1485 *err = NO_RECOVERY;
1486 return errno;
1487 diff --git a/src/network/lookup_ipliteral.c b/src/network/lookup_ipliteral.c
1488 index 2fddab73..1e766206 100644
1489 --- a/src/network/lookup_ipliteral.c
1490 +++ b/src/network/lookup_ipliteral.c
1491 @@ -15,7 +15,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil
1492 struct in6_addr a6;
1493 if (__inet_aton(name, &a4) > 0) {
1494 if (family == AF_INET6) /* wrong family */
1495 - return EAI_NONAME;
1496 + return EAI_NODATA;
1497 memcpy(&buf[0].addr, &a4, sizeof a4);
1498 buf[0].family = AF_INET;
1499 buf[0].scopeid = 0;
1500 @@ -34,7 +34,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil
1501 if (inet_pton(AF_INET6, name, &a6) <= 0)
1502 return 0;
1503 if (family == AF_INET) /* wrong family */
1504 - return EAI_NONAME;
1505 + return EAI_NODATA;
1507 memcpy(&buf[0].addr, &a6, sizeof a6);
1508 buf[0].family = AF_INET6;
1509 diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c
1510 index aa558c19..5f6867cb 100644
1511 --- a/src/network/lookup_name.c
1512 +++ b/src/network/lookup_name.c
1513 @@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
1514 case 0:
1515 continue;
1516 default:
1517 - badfam = EAI_NONAME;
1518 + badfam = EAI_NODATA;
1519 break;
1522 @@ -102,45 +102,50 @@ struct dpc_ctx {
1523 struct address *addrs;
1524 char *canon;
1525 int cnt;
1526 + int rrtype;
1529 #define RR_A 1
1530 #define RR_CNAME 5
1531 #define RR_AAAA 28
1533 +#define ABUF_SIZE 768
1535 static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet)
1537 char tmp[256];
1538 + int family;
1539 struct dpc_ctx *ctx = c;
1540 - if (ctx->cnt >= MAXADDRS) return -1;
1541 + if (rr == RR_CNAME) {
1542 + if (__dn_expand(packet, (const unsigned char *)packet + ABUF_SIZE,
1543 + data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
1544 + strcpy(ctx->canon, tmp);
1545 + return 0;
1547 + if (ctx->cnt >= MAXADDRS) return 0;
1548 + if (rr != ctx->rrtype) return 0;
1549 switch (rr) {
1550 case RR_A:
1551 if (len != 4) return -1;
1552 - ctx->addrs[ctx->cnt].family = AF_INET;
1553 - ctx->addrs[ctx->cnt].scopeid = 0;
1554 - memcpy(ctx->addrs[ctx->cnt++].addr, data, 4);
1555 + family = AF_INET;
1556 break;
1557 case RR_AAAA:
1558 if (len != 16) return -1;
1559 - ctx->addrs[ctx->cnt].family = AF_INET6;
1560 - ctx->addrs[ctx->cnt].scopeid = 0;
1561 - memcpy(ctx->addrs[ctx->cnt++].addr, data, 16);
1562 - break;
1563 - case RR_CNAME:
1564 - if (__dn_expand(packet, (const unsigned char *)packet + 512,
1565 - data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
1566 - strcpy(ctx->canon, tmp);
1567 + family = AF_INET6;
1568 break;
1570 + ctx->addrs[ctx->cnt].family = family;
1571 + ctx->addrs[ctx->cnt].scopeid = 0;
1572 + memcpy(ctx->addrs[ctx->cnt++].addr, data, len);
1573 return 0;
1576 static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, const struct resolvconf *conf)
1578 - unsigned char qbuf[2][280], abuf[2][512];
1579 + unsigned char qbuf[2][280], abuf[2][ABUF_SIZE];
1580 const unsigned char *qp[2] = { qbuf[0], qbuf[1] };
1581 unsigned char *ap[2] = { abuf[0], abuf[1] };
1582 - int qlens[2], alens[2];
1583 + int qlens[2], alens[2], qtypes[2];
1584 int i, nq = 0;
1585 struct dpc_ctx ctx = { .addrs = buf, .canon = canon };
1586 static const struct { int af; int rr; } afrr[2] = {
1587 @@ -153,8 +158,12 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
1588 qlens[nq] = __res_mkquery(0, name, 1, afrr[i].rr,
1589 0, 0, 0, qbuf[nq], sizeof *qbuf);
1590 if (qlens[nq] == -1)
1591 - return EAI_NONAME;
1592 + return 0;
1593 + qtypes[nq] = afrr[i].rr;
1594 qbuf[nq][3] = 0; /* don't need AD flag */
1595 + /* Ensure query IDs are distinct. */
1596 + if (nq && qbuf[nq][0] == qbuf[0][0])
1597 + qbuf[nq][0]++;
1598 nq++;
1601 @@ -168,11 +177,13 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
1602 if ((abuf[i][3] & 15) != 0) return EAI_FAIL;
1605 - for (i=0; i<nq; i++)
1606 + for (i=nq-1; i>=0; i--) {
1607 + ctx.rrtype = qtypes[i];
1608 __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx);
1611 if (ctx.cnt) return ctx.cnt;
1612 - return EAI_NONAME;
1613 + return EAI_NODATA;
1616 static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
1617 diff --git a/src/network/netlink.h b/src/network/netlink.h
1618 index 38acb178..873fabe2 100644
1619 --- a/src/network/netlink.h
1620 +++ b/src/network/netlink.h
1621 @@ -86,7 +86,7 @@ struct ifaddrmsg {
1622 #define RTA_DATALEN(rta) ((rta)->rta_len-sizeof(struct rtattr))
1623 #define RTA_DATAEND(rta) ((char*)(rta)+(rta)->rta_len)
1624 #define RTA_NEXT(rta) (struct rtattr*)((char*)(rta)+NETLINK_ALIGN((rta)->rta_len))
1625 -#define RTA_OK(nlh,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr))
1626 +#define RTA_OK(rta,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr))
1628 #define NLMSG_RTA(nlh,len) ((void*)((char*)(nlh)+sizeof(struct nlmsghdr)+NETLINK_ALIGN(len)))
1629 #define NLMSG_RTAOK(rta,nlh) RTA_OK(rta,NLMSG_DATAEND(nlh))
1630 diff --git a/src/network/res_mkquery.c b/src/network/res_mkquery.c
1631 index 33f50cb9..614bf786 100644
1632 --- a/src/network/res_mkquery.c
1633 +++ b/src/network/res_mkquery.c
1634 @@ -13,6 +13,7 @@ int __res_mkquery(int op, const char *dname, int class, int type,
1635 int n;
1637 if (l && dname[l-1]=='.') l--;
1638 + if (l && dname[l-1]=='.') return -1;
1639 n = 17+l+!!l;
1640 if (l>253 || buflen<n || op>15u || class>255u || type>255u)
1641 return -1;
1642 diff --git a/src/network/res_msend.c b/src/network/res_msend.c
1643 index 3e018009..11c6aa0e 100644
1644 --- a/src/network/res_msend.c
1645 +++ b/src/network/res_msend.c
1646 @@ -1,5 +1,6 @@
1647 #include <sys/socket.h>
1648 #include <netinet/in.h>
1649 +#include <netinet/tcp.h>
1650 #include <netdb.h>
1651 #include <arpa/inet.h>
1652 #include <stdint.h>
1653 @@ -16,7 +17,9 @@
1655 static void cleanup(void *p)
1657 - __syscall(SYS_close, (intptr_t)p);
1658 + struct pollfd *pfd = p;
1659 + for (int i=0; pfd[i].fd >= -1; i++)
1660 + if (pfd[i].fd >= 0) __syscall(SYS_close, pfd[i].fd);
1663 static unsigned long mtime()
1664 @@ -27,6 +30,51 @@ static unsigned long mtime()
1665 + ts.tv_nsec / 1000000;
1668 +static int start_tcp(struct pollfd *pfd, int family, const void *sa, socklen_t sl, const unsigned char *q, int ql)
1670 + struct msghdr mh = {
1671 + .msg_name = (void *)sa,
1672 + .msg_namelen = sl,
1673 + .msg_iovlen = 2,
1674 + .msg_iov = (struct iovec [2]){
1675 + { .iov_base = (uint8_t[]){ ql>>8, ql }, .iov_len = 2 },
1676 + { .iov_base = (void *)q, .iov_len = ql } }
1677 + };
1678 + int r;
1679 + int fd = socket(family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1680 + pfd->fd = fd;
1681 + pfd->events = POLLOUT;
1682 + if (!setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
1683 + &(int){1}, sizeof(int))) {
1684 + r = sendmsg(fd, &mh, MSG_FASTOPEN|MSG_NOSIGNAL);
1685 + if (r == ql+2) pfd->events = POLLIN;
1686 + if (r >= 0) return r;
1687 + if (errno == EINPROGRESS) return 0;
1689 + r = connect(fd, sa, sl);
1690 + if (!r || errno == EINPROGRESS) return 0;
1691 + close(fd);
1692 + pfd->fd = -1;
1693 + return -1;
1696 +static void step_mh(struct msghdr *mh, size_t n)
1698 + /* Adjust iovec in msghdr to skip first n bytes. */
1699 + while (mh->msg_iovlen && n >= mh->msg_iov->iov_len) {
1700 + n -= mh->msg_iov->iov_len;
1701 + mh->msg_iov++;
1702 + mh->msg_iovlen--;
1704 + if (!mh->msg_iovlen) return;
1705 + mh->msg_iov->iov_base = (char *)mh->msg_iov->iov_base + n;
1706 + mh->msg_iov->iov_len -= n;
1709 +/* Internal contract for __res_msend[_rc]: asize must be >=512, nqueries
1710 + * must be sufficiently small to be safe as VLA size. In practice it's
1711 + * either 1 or 2, anyway. */
1713 int __res_msend_rc(int nqueries, const unsigned char *const *queries,
1714 const int *qlens, unsigned char *const *answers, int *alens, int asize,
1715 const struct resolvconf *conf)
1716 @@ -44,7 +92,10 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
1717 int next;
1718 int i, j;
1719 int cs;
1720 - struct pollfd pfd;
1721 + struct pollfd pfd[nqueries+2];
1722 + int qpos[nqueries], apos[nqueries];
1723 + unsigned char alen_buf[nqueries][2];
1724 + int r;
1725 unsigned long t0, t1, t2;
1727 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
1728 @@ -68,14 +119,20 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
1731 /* Get local address and open/bind a socket */
1732 - sa.sin.sin_family = family;
1733 fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1735 /* Handle case where system lacks IPv6 support */
1736 if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
1737 + for (i=0; i<nns && conf->ns[nns].family == AF_INET6; i++);
1738 + if (i==nns) {
1739 + pthread_setcancelstate(cs, 0);
1740 + return -1;
1742 fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1743 family = AF_INET;
1744 + sl = sizeof sa.sin;
1746 + sa.sin.sin_family = family;
1747 if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) {
1748 if (fd >= 0) close(fd);
1749 pthread_setcancelstate(cs, 0);
1750 @@ -86,7 +143,12 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
1751 * yield either no reply (indicated by zero length) or an answer
1752 * packet which is up to the caller to interpret. */
1754 - pthread_cleanup_push(cleanup, (void *)(intptr_t)fd);
1755 + for (i=0; i<nqueries; i++) pfd[i].fd = -1;
1756 + pfd[nqueries].fd = fd;
1757 + pfd[nqueries].events = POLLIN;
1758 + pfd[nqueries+1].fd = -2;
1760 + pthread_cleanup_push(cleanup, pfd);
1761 pthread_setcancelstate(cs, 0);
1763 /* Convert any IPv4 addresses in a mixed environment to v4-mapped */
1764 @@ -106,14 +168,17 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
1766 memset(alens, 0, sizeof *alens * nqueries);
1768 - pfd.fd = fd;
1769 - pfd.events = POLLIN;
1770 retry_interval = timeout / attempts;
1771 next = 0;
1772 t0 = t2 = mtime();
1773 t1 = t2 - retry_interval;
1775 for (; t2-t0 < timeout; t2=mtime()) {
1776 + /* This is the loop exit condition: that all queries
1777 + * have an accepted answer. */
1778 + for (i=0; i<nqueries && alens[i]>0; i++);
1779 + if (i==nqueries) break;
1781 if (t2-t1 >= retry_interval) {
1782 /* Query all configured namservers in parallel */
1783 for (i=0; i<nqueries; i++)
1784 @@ -127,10 +192,20 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
1787 /* Wait for a response, or until time to retry */
1788 - if (poll(&pfd, 1, t1+retry_interval-t2) <= 0) continue;
1789 + if (poll(pfd, nqueries+1, t1+retry_interval-t2) <= 0) continue;
1791 - while ((rlen = recvfrom(fd, answers[next], asize, 0,
1792 - (void *)&sa, (socklen_t[1]){sl})) >= 0) {
1793 + while (next < nqueries) {
1794 + struct msghdr mh = {
1795 + .msg_name = (void *)&sa,
1796 + .msg_namelen = sl,
1797 + .msg_iovlen = 1,
1798 + .msg_iov = (struct iovec []){
1799 + { .iov_base = (void *)answers[next],
1800 + .iov_len = asize }
1802 + };
1803 + rlen = recvmsg(fd, &mh, 0);
1804 + if (rlen < 0) break;
1806 /* Ignore non-identifiable packets */
1807 if (rlen < 4) continue;
1808 @@ -170,12 +245,72 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
1809 else
1810 memcpy(answers[i], answers[next], rlen);
1812 - if (next == nqueries) goto out;
1813 + /* Ignore further UDP if all slots full or TCP-mode */
1814 + if (next == nqueries) pfd[nqueries].events = 0;
1816 + /* If answer is truncated (TC bit), fallback to TCP */
1817 + if ((answers[i][2] & 2) || (mh.msg_flags & MSG_TRUNC)) {
1818 + alens[i] = -1;
1819 + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
1820 + r = start_tcp(pfd+i, family, ns+j, sl, queries[i], qlens[i]);
1821 + pthread_setcancelstate(cs, 0);
1822 + if (r >= 0) {
1823 + qpos[i] = r;
1824 + apos[i] = 0;
1826 + continue;
1830 + for (i=0; i<nqueries; i++) if (pfd[i].revents & POLLOUT) {
1831 + struct msghdr mh = {
1832 + .msg_iovlen = 2,
1833 + .msg_iov = (struct iovec [2]){
1834 + { .iov_base = (uint8_t[]){ qlens[i]>>8, qlens[i] }, .iov_len = 2 },
1835 + { .iov_base = (void *)queries[i], .iov_len = qlens[i] } }
1836 + };
1837 + step_mh(&mh, qpos[i]);
1838 + r = sendmsg(pfd[i].fd, &mh, MSG_NOSIGNAL);
1839 + if (r < 0) goto out;
1840 + qpos[i] += r;
1841 + if (qpos[i] == qlens[i]+2)
1842 + pfd[i].events = POLLIN;
1845 + for (i=0; i<nqueries; i++) if (pfd[i].revents & POLLIN) {
1846 + struct msghdr mh = {
1847 + .msg_iovlen = 2,
1848 + .msg_iov = (struct iovec [2]){
1849 + { .iov_base = alen_buf[i], .iov_len = 2 },
1850 + { .iov_base = answers[i], .iov_len = asize } }
1851 + };
1852 + step_mh(&mh, apos[i]);
1853 + r = recvmsg(pfd[i].fd, &mh, 0);
1854 + if (r < 0) goto out;
1855 + apos[i] += r;
1856 + if (apos[i] < 2) continue;
1857 + int alen = alen_buf[i][0]*256 + alen_buf[i][1];
1858 + if (alen < 13) goto out;
1859 + if (apos[i] < alen+2 && apos[i] < asize+2)
1860 + continue;
1861 + int rcode = answers[i][3] & 15;
1862 + if (rcode != 0 && rcode != 3)
1863 + goto out;
1865 + /* Storing the length here commits the accepted answer.
1866 + * Immediately close TCP socket so as not to consume
1867 + * resources we no longer need. */
1868 + alens[i] = alen;
1869 + __syscall(SYS_close, pfd[i].fd);
1870 + pfd[i].fd = -1;
1873 out:
1874 pthread_cleanup_pop(1);
1876 + /* Disregard any incomplete TCP results */
1877 + for (i=0; i<nqueries; i++) if (alens[i]<0) alens[i] = 0;
1879 return 0;
1882 diff --git a/src/network/res_send.c b/src/network/res_send.c
1883 index ee4abf1f..9593164d 100644
1884 --- a/src/network/res_send.c
1885 +++ b/src/network/res_send.c
1886 @@ -1,8 +1,16 @@
1887 #include <resolv.h>
1888 +#include <string.h>
1890 int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen)
1892 - int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
1893 + int r;
1894 + if (anslen < 512) {
1895 + unsigned char buf[512];
1896 + r = __res_send(msg, msglen, buf, sizeof buf);
1897 + if (r >= 0) memcpy(answer, buf, r < anslen ? r : anslen);
1898 + return r;
1900 + r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
1901 return r<0 || !anslen ? -1 : anslen;
1904 diff --git a/src/process/_Fork.c b/src/process/_Fork.c
1905 index da063868..fb0fdc2c 100644
1906 --- a/src/process/_Fork.c
1907 +++ b/src/process/_Fork.c
1908 @@ -14,7 +14,6 @@ pid_t _Fork(void)
1909 pid_t ret;
1910 sigset_t set;
1911 __block_all_sigs(&set);
1912 - __aio_atfork(-1);
1913 LOCK(__abort_lock);
1914 #ifdef SYS_fork
1915 ret = __syscall(SYS_fork);
1916 @@ -32,7 +31,7 @@ pid_t _Fork(void)
1917 if (libc.need_locks) libc.need_locks = -1;
1919 UNLOCK(__abort_lock);
1920 - __aio_atfork(!ret);
1921 + if (!ret) __aio_atfork(1);
1922 __restore_sigs(&set);
1923 return __syscall_ret(ret);
1925 diff --git a/src/process/aarch64/vfork.s b/src/process/aarch64/vfork.s
1926 new file mode 100644
1927 index 00000000..429bec8c
1928 --- /dev/null
1929 +++ b/src/process/aarch64/vfork.s
1930 @@ -0,0 +1,9 @@
1931 +.global vfork
1932 +.type vfork,%function
1933 +vfork:
1934 + mov x8, 220 // SYS_clone
1935 + mov x0, 0x4111 // SIGCHLD | CLONE_VM | CLONE_VFORK
1936 + mov x1, 0
1937 + svc 0
1938 + .hidden __syscall_ret
1939 + b __syscall_ret
1940 diff --git a/src/process/fork.c b/src/process/fork.c
1941 index 54bc2892..56f19313 100644
1942 --- a/src/process/fork.c
1943 +++ b/src/process/fork.c
1944 @@ -9,7 +9,6 @@ static volatile int *const dummy_lockptr = 0;
1946 weak_alias(dummy_lockptr, __at_quick_exit_lockptr);
1947 weak_alias(dummy_lockptr, __atexit_lockptr);
1948 -weak_alias(dummy_lockptr, __dlerror_lockptr);
1949 weak_alias(dummy_lockptr, __gettext_lockptr);
1950 weak_alias(dummy_lockptr, __locale_lockptr);
1951 weak_alias(dummy_lockptr, __random_lockptr);
1952 @@ -24,7 +23,6 @@ weak_alias(dummy_lockptr, __vmlock_lockptr);
1953 static volatile int *const *const atfork_locks[] = {
1954 &__at_quick_exit_lockptr,
1955 &__atexit_lockptr,
1956 - &__dlerror_lockptr,
1957 &__gettext_lockptr,
1958 &__locale_lockptr,
1959 &__random_lockptr,
1960 @@ -38,6 +36,8 @@ static volatile int *const *const atfork_locks[] = {
1961 static void dummy(int x) { }
1962 weak_alias(dummy, __fork_handler);
1963 weak_alias(dummy, __malloc_atfork);
1964 +weak_alias(dummy, __aio_atfork);
1965 +weak_alias(dummy, __pthread_key_atfork);
1966 weak_alias(dummy, __ldso_atfork);
1968 static void dummy_0(void) { }
1969 @@ -52,6 +52,8 @@ pid_t fork(void)
1970 int need_locks = libc.need_locks > 0;
1971 if (need_locks) {
1972 __ldso_atfork(-1);
1973 + __pthread_key_atfork(-1);
1974 + __aio_atfork(-1);
1975 __inhibit_ptc();
1976 for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
1977 if (*atfork_locks[i]) LOCK(*atfork_locks[i]);
1978 @@ -77,6 +79,8 @@ pid_t fork(void)
1979 if (ret) UNLOCK(*atfork_locks[i]);
1980 else **atfork_locks[i] = 0;
1981 __release_ptc();
1982 + if (ret) __aio_atfork(0);
1983 + __pthread_key_atfork(!ret);
1984 __ldso_atfork(!ret);
1986 __restore_sigs(&set);
1987 diff --git a/src/regex/glob.c b/src/regex/glob.c
1988 index 9de080ed..a4906446 100644
1989 --- a/src/regex/glob.c
1990 +++ b/src/regex/glob.c
1991 @@ -306,6 +306,3 @@ void globfree(glob_t *g)
1992 g->gl_pathc = 0;
1993 g->gl_pathv = NULL;
1996 -weak_alias(glob, glob64);
1997 -weak_alias(globfree, globfree64);
1998 diff --git a/src/stat/__xstat.c b/src/stat/__xstat.c
1999 index 630936a0..b4560df7 100644
2000 --- a/src/stat/__xstat.c
2001 +++ b/src/stat/__xstat.c
2002 @@ -22,11 +22,6 @@ int __xstat(int ver, const char *path, struct stat *buf)
2003 return stat(path, buf);
2006 -weak_alias(__fxstat, __fxstat64);
2007 -weak_alias(__fxstatat, __fxstatat64);
2008 -weak_alias(__lxstat, __lxstat64);
2009 -weak_alias(__xstat, __xstat64);
2011 #endif
2013 int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev)
2014 diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c
2015 index 4ee00b0a..bc581050 100644
2016 --- a/src/stat/fchmodat.c
2017 +++ b/src/stat/fchmodat.c
2018 @@ -2,7 +2,6 @@
2019 #include <fcntl.h>
2020 #include <errno.h>
2021 #include "syscall.h"
2022 -#include "kstat.h"
2024 int fchmodat(int fd, const char *path, mode_t mode, int flag)
2026 @@ -11,12 +10,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
2027 if (flag != AT_SYMLINK_NOFOLLOW)
2028 return __syscall_ret(-EINVAL);
2030 - struct kstat st;
2031 + struct stat st;
2032 int ret, fd2;
2033 char proc[15+3*sizeof(int)];
2035 - if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag)))
2036 - return __syscall_ret(ret);
2037 + if (fstatat(fd, path, &st, flag))
2038 + return -1;
2039 if (S_ISLNK(st.st_mode))
2040 return __syscall_ret(-EOPNOTSUPP);
2042 @@ -27,12 +26,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
2045 __procfdname(proc, fd2);
2046 - ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0);
2047 + ret = stat(proc, &st);
2048 if (!ret) {
2049 - if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP;
2050 - else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
2051 + if (S_ISLNK(st.st_mode)) ret = __syscall_ret(-EOPNOTSUPP);
2052 + else ret = syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
2055 __syscall(SYS_close, fd2);
2056 - return __syscall_ret(ret);
2057 + return ret;
2059 diff --git a/src/stat/fstat.c b/src/stat/fstat.c
2060 index 9bbb46de..fd28b8ac 100644
2061 --- a/src/stat/fstat.c
2062 +++ b/src/stat/fstat.c
2063 @@ -4,12 +4,10 @@
2064 #include <fcntl.h>
2065 #include "syscall.h"
2067 -int fstat(int fd, struct stat *st)
2068 +int __fstat(int fd, struct stat *st)
2070 if (fd<0) return __syscall_ret(-EBADF);
2071 - return fstatat(fd, "", st, AT_EMPTY_PATH);
2072 + return __fstatat(fd, "", st, AT_EMPTY_PATH);
2075 -#if !_REDIR_TIME64
2076 -weak_alias(fstat, fstat64);
2077 -#endif
2078 +weak_alias(__fstat, fstat);
2079 diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
2080 index de165b5c..04506375 100644
2081 --- a/src/stat/fstatat.c
2082 +++ b/src/stat/fstatat.c
2083 @@ -6,7 +6,6 @@
2084 #include <stdint.h>
2085 #include <sys/sysmacros.h>
2086 #include "syscall.h"
2087 -#include "kstat.h"
2089 struct statx {
2090 uint32_t stx_mask;
2091 @@ -69,6 +68,10 @@ static int fstatat_statx(int fd, const char *restrict path, struct stat *restric
2092 return 0;
2095 +#ifdef SYS_fstatat
2097 +#include "kstat.h"
2099 static int fstatat_kstat(int fd, const char *restrict path, struct stat *restrict st, int flag)
2101 int ret;
2102 @@ -130,18 +133,21 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric
2104 return 0;
2106 +#endif
2108 -int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag)
2109 +int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag)
2111 int ret;
2112 +#ifdef SYS_fstatat
2113 if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) {
2114 ret = fstatat_statx(fd, path, st, flag);
2115 if (ret!=-ENOSYS) return __syscall_ret(ret);
2117 ret = fstatat_kstat(fd, path, st, flag);
2118 +#else
2119 + ret = fstatat_statx(fd, path, st, flag);
2120 +#endif
2121 return __syscall_ret(ret);
2124 -#if !_REDIR_TIME64
2125 -weak_alias(fstatat, fstatat64);
2126 -#endif
2127 +weak_alias(__fstatat, fstatat);
2128 diff --git a/src/stat/lstat.c b/src/stat/lstat.c
2129 index 6fe004de..6822fcae 100644
2130 --- a/src/stat/lstat.c
2131 +++ b/src/stat/lstat.c
2132 @@ -5,7 +5,3 @@ int lstat(const char *restrict path, struct stat *restrict buf)
2134 return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
2137 -#if !_REDIR_TIME64
2138 -weak_alias(lstat, lstat64);
2139 -#endif
2140 diff --git a/src/stat/stat.c b/src/stat/stat.c
2141 index ea70efc4..23570e7a 100644
2142 --- a/src/stat/stat.c
2143 +++ b/src/stat/stat.c
2144 @@ -5,7 +5,3 @@ int stat(const char *restrict path, struct stat *restrict buf)
2146 return fstatat(AT_FDCWD, path, buf, 0);
2149 -#if !_REDIR_TIME64
2150 -weak_alias(stat, stat64);
2151 -#endif
2152 diff --git a/src/stat/statvfs.c b/src/stat/statvfs.c
2153 index f65d1b54..bfbb5fee 100644
2154 --- a/src/stat/statvfs.c
2155 +++ b/src/stat/statvfs.c
2156 @@ -56,8 +56,3 @@ int fstatvfs(int fd, struct statvfs *buf)
2157 fixup(buf, &kbuf);
2158 return 0;
2161 -weak_alias(statvfs, statvfs64);
2162 -weak_alias(statfs, statfs64);
2163 -weak_alias(fstatvfs, fstatvfs64);
2164 -weak_alias(fstatfs, fstatfs64);
2165 diff --git a/src/stdio/fgetpos.c b/src/stdio/fgetpos.c
2166 index 50813d2c..392f7323 100644
2167 --- a/src/stdio/fgetpos.c
2168 +++ b/src/stdio/fgetpos.c
2169 @@ -7,5 +7,3 @@ int fgetpos(FILE *restrict f, fpos_t *restrict pos)
2170 *(long long *)pos = off;
2171 return 0;
2174 -weak_alias(fgetpos, fgetpos64);
2175 diff --git a/src/stdio/fgets.c b/src/stdio/fgets.c
2176 index 6171f398..4a100b39 100644
2177 --- a/src/stdio/fgets.c
2178 +++ b/src/stdio/fgets.c
2179 @@ -12,13 +12,14 @@ char *fgets(char *restrict s, int n, FILE *restrict f)
2181 FLOCK(f);
2183 - if (n--<=1) {
2184 + if (n<=1) {
2185 f->mode |= f->mode-1;
2186 FUNLOCK(f);
2187 - if (n) return 0;
2188 + if (n<1) return 0;
2189 *s = 0;
2190 return s;
2192 + n--;
2194 while (n) {
2195 if (f->rpos != f->rend) {
2196 diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c
2197 index e1b91e12..80bc341e 100644
2198 --- a/src/stdio/fopen.c
2199 +++ b/src/stdio/fopen.c
2200 @@ -29,5 +29,3 @@ FILE *fopen(const char *restrict filename, const char *restrict mode)
2201 __syscall(SYS_close, fd);
2202 return 0;
2205 -weak_alias(fopen, fopen64);
2206 diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c
2207 index 615d4b47..1641a4c5 100644
2208 --- a/src/stdio/freopen.c
2209 +++ b/src/stdio/freopen.c
2210 @@ -40,6 +40,8 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re
2211 fclose(f2);
2214 + f->mode = 0;
2215 + f->locale = 0;
2216 FUNLOCK(f);
2217 return f;
2219 @@ -49,5 +51,3 @@ fail:
2220 fclose(f);
2221 return NULL;
2224 -weak_alias(freopen, freopen64);
2225 diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c
2226 index c07f7e95..c7425802 100644
2227 --- a/src/stdio/fseek.c
2228 +++ b/src/stdio/fseek.c
2229 @@ -46,5 +46,3 @@ int fseek(FILE *f, long off, int whence)
2232 weak_alias(__fseeko, fseeko);
2234 -weak_alias(fseeko, fseeko64);
2235 diff --git a/src/stdio/fsetpos.c b/src/stdio/fsetpos.c
2236 index 77ab8d82..779cb3cc 100644
2237 --- a/src/stdio/fsetpos.c
2238 +++ b/src/stdio/fsetpos.c
2239 @@ -4,5 +4,3 @@ int fsetpos(FILE *f, const fpos_t *pos)
2241 return __fseeko(f, *(const long long *)pos, SEEK_SET);
2244 -weak_alias(fsetpos, fsetpos64);
2245 diff --git a/src/stdio/ftell.c b/src/stdio/ftell.c
2246 index 1a2afbbc..1e1a08d8 100644
2247 --- a/src/stdio/ftell.c
2248 +++ b/src/stdio/ftell.c
2249 @@ -37,5 +37,3 @@ long ftell(FILE *f)
2252 weak_alias(__ftello, ftello);
2254 -weak_alias(ftello, ftello64);
2255 diff --git a/src/stdio/open_wmemstream.c b/src/stdio/open_wmemstream.c
2256 index ed1b561d..b8ae4a79 100644
2257 --- a/src/stdio/open_wmemstream.c
2258 +++ b/src/stdio/open_wmemstream.c
2259 @@ -40,8 +40,12 @@ fail:
2260 static size_t wms_write(FILE *f, const unsigned char *buf, size_t len)
2262 struct cookie *c = f->cookie;
2263 - size_t len2;
2264 + size_t len2 = f->wpos - f->wbase;
2265 wchar_t *newbuf;
2266 + if (len2) {
2267 + f->wpos = f->wbase;
2268 + if (wms_write(f, f->wbase, len2) < len2) return 0;
2270 if (len + c->pos >= c->space) {
2271 len2 = 2*c->space+1 | c->pos+len+1;
2272 if (len2 > SSIZE_MAX/4) return 0;
2273 diff --git a/src/stdio/tempnam.c b/src/stdio/tempnam.c
2274 index 565df6b6..0c65b1f0 100644
2275 --- a/src/stdio/tempnam.c
2276 +++ b/src/stdio/tempnam.c
2277 @@ -6,7 +6,6 @@
2278 #include <string.h>
2279 #include <stdlib.h>
2280 #include "syscall.h"
2281 -#include "kstat.h"
2283 #define MAXTRIES 100
2285 @@ -37,11 +36,10 @@ char *tempnam(const char *dir, const char *pfx)
2287 for (try=0; try<MAXTRIES; try++) {
2288 __randname(s+l-6);
2289 -#ifdef SYS_lstat
2290 - r = __syscall(SYS_lstat, s, &(struct kstat){0});
2291 +#ifdef SYS_readlink
2292 + r = __syscall(SYS_readlink, s, (char[1]){0}, 1);
2293 #else
2294 - r = __syscall(SYS_fstatat, AT_FDCWD, s,
2295 - &(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
2296 + r = __syscall(SYS_readlinkat, AT_FDCWD, s, (char[1]){0}, 1);
2297 #endif
2298 if (r == -ENOENT) return strdup(s);
2300 diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c
2301 index ae493987..2fa8803f 100644
2302 --- a/src/stdio/tmpfile.c
2303 +++ b/src/stdio/tmpfile.c
2304 @@ -27,5 +27,3 @@ FILE *tmpfile(void)
2306 return 0;
2309 -weak_alias(tmpfile, tmpfile64);
2310 diff --git a/src/stdio/tmpnam.c b/src/stdio/tmpnam.c
2311 index d667a836..71dc8bb1 100644
2312 --- a/src/stdio/tmpnam.c
2313 +++ b/src/stdio/tmpnam.c
2314 @@ -5,7 +5,6 @@
2315 #include <string.h>
2316 #include <stdlib.h>
2317 #include "syscall.h"
2318 -#include "kstat.h"
2320 #define MAXTRIES 100
2322 @@ -17,11 +16,10 @@ char *tmpnam(char *buf)
2323 int r;
2324 for (try=0; try<MAXTRIES; try++) {
2325 __randname(s+12);
2326 -#ifdef SYS_lstat
2327 - r = __syscall(SYS_lstat, s, &(struct kstat){0});
2328 +#ifdef SYS_readlink
2329 + r = __syscall(SYS_readlink, s, (char[1]){0}, 1);
2330 #else
2331 - r = __syscall(SYS_fstatat, AT_FDCWD, s,
2332 - &(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
2333 + r = __syscall(SYS_readlinkat, AT_FDCWD, s, (char[1]){0}, 1);
2334 #endif
2335 if (r == -ENOENT) return strcpy(buf ? buf : internal, s);
2337 diff --git a/src/stdlib/qsort_nr.c b/src/stdlib/qsort_nr.c
2338 index efe7ccec..8ffe71d0 100644
2339 --- a/src/stdlib/qsort_nr.c
2340 +++ b/src/stdlib/qsort_nr.c
2341 @@ -10,5 +10,5 @@ static int wrapper_cmp(const void *v1, const void *v2, void *cmp)
2343 void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
2345 - __qsort_r(base, nel, width, wrapper_cmp, cmp);
2346 + __qsort_r(base, nel, width, wrapper_cmp, (void *)cmp);
2348 diff --git a/src/temp/__randname.c b/src/temp/__randname.c
2349 index 2bce37a0..e9b970f1 100644
2350 --- a/src/temp/__randname.c
2351 +++ b/src/temp/__randname.c
2352 @@ -1,5 +1,6 @@
2353 #include <time.h>
2354 #include <stdint.h>
2355 +#include "pthread_impl.h"
2357 /* This assumes that a check for the
2358 template size has already been made */
2359 @@ -10,7 +11,7 @@ char *__randname(char *template)
2360 unsigned long r;
2362 __clock_gettime(CLOCK_REALTIME, &ts);
2363 - r = ts.tv_nsec*65537 ^ (uintptr_t)&ts / 16 + (uintptr_t)template;
2364 + r = ts.tv_sec + ts.tv_nsec + __pthread_self()->tid * 65537UL;
2365 for (i=0; i<6; i++, r>>=5)
2366 template[i] = 'A'+(r&15)+(r&16)*2;
2368 diff --git a/src/temp/mkostemp.c b/src/temp/mkostemp.c
2369 index d8dcb805..e3dfdd91 100644
2370 --- a/src/temp/mkostemp.c
2371 +++ b/src/temp/mkostemp.c
2372 @@ -5,5 +5,3 @@ int mkostemp(char *template, int flags)
2374 return __mkostemps(template, 0, flags);
2377 -weak_alias(mkostemp, mkostemp64);
2378 diff --git a/src/temp/mkostemps.c b/src/temp/mkostemps.c
2379 index ef24eeae..093d2380 100644
2380 --- a/src/temp/mkostemps.c
2381 +++ b/src/temp/mkostemps.c
2382 @@ -26,4 +26,3 @@ int __mkostemps(char *template, int len, int flags)
2385 weak_alias(__mkostemps, mkostemps);
2386 -weak_alias(__mkostemps, mkostemps64);
2387 diff --git a/src/temp/mkstemp.c b/src/temp/mkstemp.c
2388 index 166b8afe..76c835bb 100644
2389 --- a/src/temp/mkstemp.c
2390 +++ b/src/temp/mkstemp.c
2391 @@ -4,5 +4,3 @@ int mkstemp(char *template)
2393 return __mkostemps(template, 0, 0);
2396 -weak_alias(mkstemp, mkstemp64);
2397 diff --git a/src/temp/mkstemps.c b/src/temp/mkstemps.c
2398 index 6b7531b5..f8eabfec 100644
2399 --- a/src/temp/mkstemps.c
2400 +++ b/src/temp/mkstemps.c
2401 @@ -5,5 +5,3 @@ int mkstemps(char *template, int len)
2403 return __mkostemps(template, len, 0);
2406 -weak_alias(mkstemps, mkstemps64);
2407 diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
2408 index 2f9d5e97..2d3a98ea 100644
2409 --- a/src/thread/pthread_cancel.c
2410 +++ b/src/thread/pthread_cancel.c
2411 @@ -77,7 +77,7 @@ void __testcancel()
2412 static void init_cancellation()
2414 struct sigaction sa = {
2415 - .sa_flags = SA_SIGINFO | SA_RESTART,
2416 + .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK,
2417 .sa_sigaction = cancel_handler
2419 memset(&sa.sa_mask, -1, _NSIG/8);
2420 diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
2421 index 6f187ee8..087f6206 100644
2422 --- a/src/thread/pthread_create.c
2423 +++ b/src/thread/pthread_create.c
2424 @@ -107,6 +107,16 @@ _Noreturn void __pthread_exit(void *result)
2426 /* At this point we are committed to thread termination. */
2428 + /* After the kernel thread exits, its tid may be reused. Clear it
2429 + * to prevent inadvertent use and inform functions that would use
2430 + * it that it's no longer available. At this point the killlock
2431 + * may be released, since functions that use it will consistently
2432 + * see the thread as having exited. Release it now so that no
2433 + * remaining locks (except thread list) are held if we end up
2434 + * resetting need_locks below. */
2435 + self->tid = 0;
2436 + UNLOCK(self->killlock);
2438 /* Process robust list in userspace to handle non-pshared mutexes
2439 * and the detached thread case where the robust list head will
2440 * be invalid when the kernel would process it. */
2441 @@ -159,12 +169,6 @@ _Noreturn void __pthread_exit(void *result)
2442 a_store(&self->detach_state, DT_EXITED);
2443 __wake(&self->detach_state, 1, 1);
2445 - /* After the kernel thread exits, its tid may be reused. Clear it
2446 - * to prevent inadvertent use and inform functions that would use
2447 - * it that it's no longer available. */
2448 - self->tid = 0;
2449 - UNLOCK(self->killlock);
2451 for (;;) __syscall(SYS_exit, 0);
2454 diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c
2455 index d1120941..39770c7a 100644
2456 --- a/src/thread/pthread_key_create.c
2457 +++ b/src/thread/pthread_key_create.c
2458 @@ -1,4 +1,5 @@
2459 #include "pthread_impl.h"
2460 +#include "fork_impl.h"
2462 volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX;
2463 void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 };
2464 @@ -20,6 +21,13 @@ static void dummy_0(void)
2465 weak_alias(dummy_0, __tl_lock);
2466 weak_alias(dummy_0, __tl_unlock);
2468 +void __pthread_key_atfork(int who)
2470 + if (who<0) __pthread_rwlock_rdlock(&key_lock);
2471 + else if (!who) __pthread_rwlock_unlock(&key_lock);
2472 + else key_lock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER;
2475 int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
2477 pthread_t self = __pthread_self();
2478 diff --git a/src/thread/synccall.c b/src/thread/synccall.c
2479 index d58c851f..a6b177c0 100644
2480 --- a/src/thread/synccall.c
2481 +++ b/src/thread/synccall.c
2482 @@ -45,7 +45,7 @@ void __synccall(void (*func)(void *), void *ctx)
2484 sigset_t oldmask;
2485 int cs, i, r;
2486 - struct sigaction sa = { .sa_flags = SA_RESTART, .sa_handler = handler };
2487 + struct sigaction sa = { .sa_flags = SA_RESTART | SA_ONSTACK, .sa_handler = handler };
2488 pthread_t self = __pthread_self(), td;
2489 int count = 0;
2491 diff --git a/src/time/__map_file.c b/src/time/__map_file.c
2492 index d3cefa82..c2b29fe8 100644
2493 --- a/src/time/__map_file.c
2494 +++ b/src/time/__map_file.c
2495 @@ -2,15 +2,14 @@
2496 #include <fcntl.h>
2497 #include <sys/stat.h>
2498 #include "syscall.h"
2499 -#include "kstat.h"
2501 const char unsigned *__map_file(const char *pathname, size_t *size)
2503 - struct kstat st;
2504 + struct stat st;
2505 const unsigned char *map = MAP_FAILED;
2506 int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
2507 if (fd < 0) return 0;
2508 - if (!syscall(SYS_fstat, fd, &st)) {
2509 + if (!__fstat(fd, &st)) {
2510 map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
2511 *size = st.st_size;
2513 diff --git a/src/time/clock_getcpuclockid.c b/src/time/clock_getcpuclockid.c
2514 index 8a0e2d4c..bce1e8ab 100644
2515 --- a/src/time/clock_getcpuclockid.c
2516 +++ b/src/time/clock_getcpuclockid.c
2517 @@ -8,6 +8,7 @@ int clock_getcpuclockid(pid_t pid, clockid_t *clk)
2518 struct timespec ts;
2519 clockid_t id = (-pid-1)*8U + 2;
2520 int ret = __syscall(SYS_clock_getres, id, &ts);
2521 + if (ret == -EINVAL) ret = -ESRCH;
2522 if (ret) return -ret;
2523 *clk = id;
2524 return 0;
2525 diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c
2526 index 3e1d0975..4d2ec22f 100644
2527 --- a/src/time/clock_gettime.c
2528 +++ b/src/time/clock_gettime.c
2529 @@ -42,6 +42,9 @@ static int cgt_init(clockid_t clk, struct timespec *ts)
2530 p = cgt_time32_wrap;
2533 +#ifdef VDSO_CGT_WORKAROUND
2534 + if (!__vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM)) p = 0;
2535 +#endif
2536 #endif
2537 int (*f)(clockid_t, struct timespec *) =
2538 (int (*)(clockid_t, struct timespec *))p;
2539 @@ -80,10 +83,12 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
2540 return __syscall_ret(r);
2541 long ts32[2];
2542 r = __syscall(SYS_clock_gettime, clk, ts32);
2543 +#ifdef SYS_gettimeofday
2544 if (r==-ENOSYS && clk==CLOCK_REALTIME) {
2545 r = __syscall(SYS_gettimeofday, ts32, 0);
2546 ts32[1] *= 1000;
2548 +#endif
2549 if (!r) {
2550 ts->tv_sec = ts32[0];
2551 ts->tv_nsec = ts32[1];
2552 @@ -92,6 +97,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
2553 return __syscall_ret(r);
2554 #else
2555 r = __syscall(SYS_clock_gettime, clk, ts);
2556 +#ifdef SYS_gettimeofday
2557 if (r == -ENOSYS) {
2558 if (clk == CLOCK_REALTIME) {
2559 __syscall(SYS_gettimeofday, ts, 0);
2560 @@ -100,6 +106,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
2562 r = -EINVAL;
2564 +#endif
2565 return __syscall_ret(r);
2566 #endif
2568 diff --git a/src/time/timer_create.c b/src/time/timer_create.c
2569 index 4bef2390..cd32c945 100644
2570 --- a/src/time/timer_create.c
2571 +++ b/src/time/timer_create.c
2572 @@ -43,6 +43,8 @@ static void *start(void *arg)
2573 union sigval val = args->sev->sigev_value;
2575 pthread_barrier_wait(&args->b);
2576 + if (self->cancel)
2577 + return 0;
2578 for (;;) {
2579 siginfo_t si;
2580 while (sigwaitinfo(SIGTIMER_SET, &si) < 0);
2581 @@ -113,8 +115,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
2582 ksev.sigev_signo = SIGTIMER;
2583 ksev.sigev_notify = SIGEV_THREAD_ID;
2584 ksev.sigev_tid = td->tid;
2585 - if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
2586 + if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) {
2587 timerid = -1;
2588 + td->cancel = 1;
2590 td->timer_id = timerid;
2591 pthread_barrier_wait(&args.b);
2592 if (timerid < 0) return -1;
2593 diff --git a/src/unistd/ftruncate.c b/src/unistd/ftruncate.c
2594 index b41be0fa..54ff34bc 100644
2595 --- a/src/unistd/ftruncate.c
2596 +++ b/src/unistd/ftruncate.c
2597 @@ -5,5 +5,3 @@ int ftruncate(int fd, off_t length)
2599 return syscall(SYS_ftruncate, fd, __SYSCALL_LL_O(length));
2602 -weak_alias(ftruncate, ftruncate64);
2603 diff --git a/src/unistd/lseek.c b/src/unistd/lseek.c
2604 index b4984f3e..f5b66682 100644
2605 --- a/src/unistd/lseek.c
2606 +++ b/src/unistd/lseek.c
2607 @@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence)
2610 weak_alias(__lseek, lseek);
2611 -weak_alias(__lseek, lseek64);
2612 diff --git a/src/unistd/mipsn32/lseek.c b/src/unistd/mipsn32/lseek.c
2613 index 60e74a51..0f6cbcaa 100644
2614 --- a/src/unistd/mipsn32/lseek.c
2615 +++ b/src/unistd/mipsn32/lseek.c
2616 @@ -17,4 +17,3 @@ off_t __lseek(int fd, off_t offset, int whence)
2619 weak_alias(__lseek, lseek);
2620 -weak_alias(__lseek, lseek64);
2621 diff --git a/src/unistd/pread.c b/src/unistd/pread.c
2622 index 5681b045..b03fb0ad 100644
2623 --- a/src/unistd/pread.c
2624 +++ b/src/unistd/pread.c
2625 @@ -5,5 +5,3 @@ ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
2627 return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_PRW(ofs));
2630 -weak_alias(pread, pread64);
2631 diff --git a/src/unistd/preadv.c b/src/unistd/preadv.c
2632 index 8376d60f..890ab403 100644
2633 --- a/src/unistd/preadv.c
2634 +++ b/src/unistd/preadv.c
2635 @@ -8,5 +8,3 @@ ssize_t preadv(int fd, const struct iovec *iov, int count, off_t ofs)
2636 return syscall_cp(SYS_preadv, fd, iov, count,
2637 (long)(ofs), (long)(ofs>>32));
2640 -weak_alias(preadv, preadv64);
2641 diff --git a/src/unistd/pwrite.c b/src/unistd/pwrite.c
2642 index ca376576..869b69f0 100644
2643 --- a/src/unistd/pwrite.c
2644 +++ b/src/unistd/pwrite.c
2645 @@ -5,5 +5,3 @@ ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
2647 return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_PRW(ofs));
2650 -weak_alias(pwrite, pwrite64);
2651 diff --git a/src/unistd/pwritev.c b/src/unistd/pwritev.c
2652 index f5a612c4..becf9deb 100644
2653 --- a/src/unistd/pwritev.c
2654 +++ b/src/unistd/pwritev.c
2655 @@ -8,5 +8,3 @@ ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs)
2656 return syscall_cp(SYS_pwritev, fd, iov, count,
2657 (long)(ofs), (long)(ofs>>32));
2660 -weak_alias(pwritev, pwritev64);
2661 diff --git a/src/unistd/truncate.c b/src/unistd/truncate.c
2662 index 97296800..077351e1 100644
2663 --- a/src/unistd/truncate.c
2664 +++ b/src/unistd/truncate.c
2665 @@ -5,5 +5,3 @@ int truncate(const char *path, off_t length)
2667 return syscall(SYS_truncate, path, __SYSCALL_LL_O(length));
2670 -weak_alias(truncate, truncate64);
2671 diff --git a/src/unistd/x32/lseek.c b/src/unistd/x32/lseek.c
2672 index 32636429..5f93292f 100644
2673 --- a/src/unistd/x32/lseek.c
2674 +++ b/src/unistd/x32/lseek.c
2675 @@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence)
2678 weak_alias(__lseek, lseek);
2679 -weak_alias(__lseek, lseek64);