summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/syscall_arch.h7
-rw-r--r--compat/time32/__xstat.c8
-rw-r--r--compat/time32/aio_suspend_time32.c2
-rw-r--r--compat/time32/fstat_time32.c2
-rw-r--r--compat/time32/fstatat_time32.c2
-rw-r--r--compat/time32/lstat_time32.c2
-rw-r--r--compat/time32/stat_time32.c2
-rwxr-xr-xconfigure8
-rw-r--r--include/aio.h2
-rw-r--r--include/arpa/nameser.h71
-rw-r--r--include/dirent.h2
-rw-r--r--include/fcntl.h2
-rw-r--r--include/ftw.h2
-rw-r--r--include/glob.h2
-rw-r--r--include/netdb.h1
-rw-r--r--include/stdio.h2
-rw-r--r--include/stdlib.h2
-rw-r--r--include/sys/mman.h2
-rw-r--r--include/sys/resource.h2
-rw-r--r--include/sys/sendfile.h2
-rw-r--r--include/sys/stat.h2
-rw-r--r--include/sys/statfs.h2
-rw-r--r--include/sys/statvfs.h2
-rw-r--r--include/sys/types.h2
-rw-r--r--include/sys/uio.h2
-rw-r--r--include/unistd.h4
-rw-r--r--ldso/dlstart.c15
-rw-r--r--ldso/dynlink.c36
-rw-r--r--src/aio/aio.c32
-rw-r--r--src/aio/aio_suspend.c6
-rw-r--r--src/aio/lio_listio.c2
-rw-r--r--src/conf/sysconf.c13
-rw-r--r--src/dirent/alphasort.c2
-rw-r--r--src/dirent/readdir.c2
-rw-r--r--src/dirent/readdir_r.c2
-rw-r--r--src/dirent/scandir.c2
-rw-r--r--src/dirent/versionsort.c3
-rw-r--r--src/fcntl/creat.c2
-rw-r--r--src/fcntl/open.c2
-rw-r--r--src/fcntl/openat.c2
-rw-r--r--src/fcntl/posix_fadvise.c2
-rw-r--r--src/fcntl/posix_fallocate.c2
-rw-r--r--src/internal/fork_impl.h2
-rw-r--r--src/ldso/dlerror.c34
-rw-r--r--src/legacy/ftw.c2
-rw-r--r--src/linux/epoll.c1
-rw-r--r--src/linux/fallocate.c3
-rw-r--r--src/linux/getdents.c2
-rw-r--r--src/linux/membarrier.c2
-rw-r--r--src/linux/prlimit.c3
-rw-r--r--src/linux/sendfile.c2
-rw-r--r--src/malloc/mallocng/free.c2
-rw-r--r--src/malloc/mallocng/glue.h2
-rw-r--r--src/misc/getrlimit.c2
-rw-r--r--src/misc/lockf.c2
-rw-r--r--src/misc/nftw.c2
-rw-r--r--src/misc/setrlimit.c2
-rw-r--r--src/mman/mmap.c2
-rw-r--r--src/network/gai_strerror.c2
-rw-r--r--src/network/getaddrinfo.c5
-rw-r--r--src/network/gethostbyaddr.c2
-rw-r--r--src/network/gethostbyaddr_r.c5
-rw-r--r--src/network/gethostbyname2.c2
-rw-r--r--src/network/gethostbyname2_r.c6
-rw-r--r--src/network/lookup_ipliteral.c4
-rw-r--r--src/network/lookup_name.c44
-rw-r--r--src/network/res_mkquery.c1
-rw-r--r--src/network/res_msend.c155
-rw-r--r--src/network/res_send.c10
-rw-r--r--src/process/_Fork.c3
-rw-r--r--src/process/fork.c8
-rw-r--r--src/regex/glob.c3
-rw-r--r--src/stat/__xstat.c5
-rw-r--r--src/stat/fstat.c4
-rw-r--r--src/stat/fstatat.c4
-rw-r--r--src/stat/lstat.c4
-rw-r--r--src/stat/stat.c4
-rw-r--r--src/stat/statvfs.c5
-rw-r--r--src/stdio/fgetpos.c2
-rw-r--r--src/stdio/fgets.c5
-rw-r--r--src/stdio/fopen.c2
-rw-r--r--src/stdio/freopen.c4
-rw-r--r--src/stdio/fseek.c2
-rw-r--r--src/stdio/fsetpos.c2
-rw-r--r--src/stdio/ftell.c2
-rw-r--r--src/stdio/open_wmemstream.c6
-rw-r--r--src/stdio/tmpfile.c2
-rw-r--r--src/temp/mkostemp.c2
-rw-r--r--src/temp/mkostemps.c1
-rw-r--r--src/temp/mkstemp.c2
-rw-r--r--src/temp/mkstemps.c2
-rw-r--r--src/thread/pthread_cancel.c2
-rw-r--r--src/thread/pthread_create.c16
-rw-r--r--src/thread/pthread_key_create.c8
-rw-r--r--src/thread/synccall.c2
-rw-r--r--src/time/clock_gettime.c3
-rw-r--r--src/time/timer_create.c6
-rw-r--r--src/unistd/ftruncate.c2
-rw-r--r--src/unistd/lseek.c1
-rw-r--r--src/unistd/mipsn32/lseek.c1
-rw-r--r--src/unistd/pread.c2
-rw-r--r--src/unistd/preadv.c2
-rw-r--r--src/unistd/pwrite.c2
-rw-r--r--src/unistd/pwritev.c2
-rw-r--r--src/unistd/truncate.c2
-rw-r--r--src/unistd/x32/lseek.c1
106 files changed, 462 insertions, 229 deletions
diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h
index a877b2cf..624e992e 100644
--- a/arch/arm/syscall_arch.h
+++ b/arch/arm/syscall_arch.h
@@ -101,3 +101,10 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
#define SYSCALL_FADVISE_6_ARG
#define SYSCALL_IPC_BROKEN_MODE
+
+#define VDSO_USEFUL
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
+#define VDSO_CGT_VER "LINUX_2.6"
+#define VDSO_CGT_WORKAROUND 1
diff --git a/compat/time32/__xstat.c b/compat/time32/__xstat.c
index acfbd3cc..e52b5deb 100644
--- a/compat/time32/__xstat.c
+++ b/compat/time32/__xstat.c
@@ -3,22 +3,22 @@
struct stat32;
-int __fxstat64(int ver, int fd, struct stat32 *buf)
+int __fxstat(int ver, int fd, struct stat32 *buf)
{
return __fstat_time32(fd, buf);
}
-int __fxstatat64(int ver, int fd, const char *path, struct stat32 *buf, int flag)
+int __fxstatat(int ver, int fd, const char *path, struct stat32 *buf, int flag)
{
return __fstatat_time32(fd, path, buf, flag);
}
-int __lxstat64(int ver, const char *path, struct stat32 *buf)
+int __lxstat(int ver, const char *path, struct stat32 *buf)
{
return __lstat_time32(path, buf);
}
-int __xstat64(int ver, const char *path, struct stat32 *buf)
+int __xstat(int ver, const char *path, struct stat32 *buf)
{
return __stat_time32(path, buf);
}
diff --git a/compat/time32/aio_suspend_time32.c b/compat/time32/aio_suspend_time32.c
index ed5119bd..d99cb651 100644
--- a/compat/time32/aio_suspend_time32.c
+++ b/compat/time32/aio_suspend_time32.c
@@ -7,5 +7,3 @@ int __aio_suspend_time32(const struct aiocb *const cbs[], int cnt, const struct
return aio_suspend(cbs, cnt, ts32 ? (&(struct timespec){
.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
}
-
-weak_alias(aio_suspend, aio_suspend64);
diff --git a/compat/time32/fstat_time32.c b/compat/time32/fstat_time32.c
index 3e084398..e5d52022 100644
--- a/compat/time32/fstat_time32.c
+++ b/compat/time32/fstat_time32.c
@@ -13,5 +13,3 @@ int __fstat_time32(int fd, struct stat32 *restrict st32)
if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
return r;
}
-
-weak_alias(fstat, fstat64);
diff --git a/compat/time32/fstatat_time32.c b/compat/time32/fstatat_time32.c
index 85dcb008..31d42e63 100644
--- a/compat/time32/fstatat_time32.c
+++ b/compat/time32/fstatat_time32.c
@@ -13,5 +13,3 @@ int __fstatat_time32(int fd, const char *restrict path, struct stat32 *restrict
if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
return r;
}
-
-weak_alias(fstatat, fstatat64);
diff --git a/compat/time32/lstat_time32.c b/compat/time32/lstat_time32.c
index c1257a14..28cb5a0b 100644
--- a/compat/time32/lstat_time32.c
+++ b/compat/time32/lstat_time32.c
@@ -13,5 +13,3 @@ int __lstat_time32(const char *restrict path, struct stat32 *restrict st32)
if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
return r;
}
-
-weak_alias(lstat, lstat64);
diff --git a/compat/time32/stat_time32.c b/compat/time32/stat_time32.c
index 8c6121da..b154b0f9 100644
--- a/compat/time32/stat_time32.c
+++ b/compat/time32/stat_time32.c
@@ -13,5 +13,3 @@ int __stat_time32(const char *restrict path, struct stat32 *restrict st32)
if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
return r;
}
-
-weak_alias(stat, stat64);
diff --git a/configure b/configure
index 6f5453f5..853bf05e 100755
--- a/configure
+++ b/configure
@@ -354,6 +354,14 @@ tryflag CFLAGS_C99FSE -fexcess-precision=standard \
tryflag CFLAGS_C99FSE -frounding-math
#
+# Semantically we want to insist that our sources follow the
+# C rules for type-based aliasing, but most if not all real-world
+# compilers are known or suspected to have critical bugs in their
+# type-based aliasing analysis. See for example GCC bug 107107.
+#
+tryflag CFLAGS_C99FSE -fno-strict-aliasing
+
+#
# We may use the may_alias attribute if __GNUC__ is defined, so
# if the compiler defines __GNUC__ but does not provide it,
# it must be defined away as part of the CFLAGS.
diff --git a/include/aio.h b/include/aio.h
index 453c41b7..a938fcad 100644
--- a/include/aio.h
+++ b/include/aio.h
@@ -49,7 +49,7 @@ int aio_fsync(int, struct aiocb *);
int lio_listio(int, struct aiocb *__restrict const *__restrict, int, struct sigevent *__restrict);
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define aiocb64 aiocb
#define aio_read64 aio_read
#define aio_write64 aio_write
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
index 581925a4..9c1327a1 100644
--- a/include/arpa/nameser.h
+++ b/include/arpa/nameser.h
@@ -188,6 +188,36 @@ typedef enum __ns_type {
ns_t_sink = 40,
ns_t_opt = 41,
ns_t_apl = 42,
+ ns_t_ds = 43,
+ ns_t_sshfp = 44,
+ ns_t_ipseckey = 45,
+ ns_t_rrsig = 46,
+ ns_t_nsec = 47,
+ ns_t_dnskey = 48,
+ ns_t_dhcid = 49,
+ ns_t_nsec3 = 50,
+ ns_t_nsec3param = 51,
+ ns_t_tlsa = 52,
+ ns_t_smimea = 53,
+ ns_t_hip = 55,
+ ns_t_ninfo = 56,
+ ns_t_rkey = 57,
+ ns_t_talink = 58,
+ ns_t_cds = 59,
+ ns_t_cdnskey = 60,
+ ns_t_openpgpkey = 61,
+ ns_t_csync = 62,
+ ns_t_spf = 99,
+ ns_t_uinfo = 100,
+ ns_t_uid = 101,
+ ns_t_gid = 102,
+ ns_t_unspec = 103,
+ ns_t_nid = 104,
+ ns_t_l32 = 105,
+ ns_t_l64 = 106,
+ ns_t_lp = 107,
+ ns_t_eui48 = 108,
+ ns_t_eui64 = 109,
ns_t_tkey = 249,
ns_t_tsig = 250,
ns_t_ixfr = 251,
@@ -196,6 +226,11 @@ typedef enum __ns_type {
ns_t_maila = 254,
ns_t_any = 255,
ns_t_zxfr = 256,
+ ns_t_uri = 256,
+ ns_t_caa = 257,
+ ns_t_avc = 258,
+ ns_t_ta = 32768,
+ ns_t_dlv = 32769,
ns_t_max = 65536
} ns_type;
@@ -430,12 +465,48 @@ typedef struct {
#define T_NAPTR ns_t_naptr
#define T_A6 ns_t_a6
#define T_DNAME ns_t_dname
+#define T_DS ns_t_ds
+#define T_SSHFP ns_t_sshfp
+#define T_IPSECKEY ns_t_ipseckey
+#define T_RRSIG ns_t_rrsig
+#define T_NSEC ns_t_nsec
+#define T_DNSKEY ns_t_dnskey
+#define T_DHCID ns_t_dhcid
+#define T_NSEC3 ns_t_nsec3
+#define T_NSEC3PARAM ns_t_nsec3param
+#define T_TLSA ns_t_tlsa
+#define T_SMIMEA ns_t_smimea
+#define T_HIP ns_t_hip
+#define T_NINFO ns_t_ninfo
+#define T_RKEY ns_t_rkey
+#define T_TALINK ns_t_talink
+#define T_CDS ns_t_cds
+#define T_CDNSKEY ns_t_cdnskey
+#define T_OPENPGPKEY ns_t_openpgpkey
+#define T_CSYNC ns_t_csync
+#define T_SPF ns_t_spf
+#define T_UINFO ns_t_uinfo
+#define T_UID ns_t_uid
+#define T_GID ns_t_gid
+#define T_UNSPEC ns_t_unspec
+#define T_NID ns_t_nid
+#define T_L32 ns_t_l32
+#define T_L64 ns_t_l64
+#define T_LP ns_t_lp
+#define T_EUI48 ns_t_eui48
+#define T_EUI64 ns_t_eui64
+#define T_TKEY ns_t_tkey
#define T_TSIG ns_t_tsig
#define T_IXFR ns_t_ixfr
#define T_AXFR ns_t_axfr
#define T_MAILB ns_t_mailb
#define T_MAILA ns_t_maila
#define T_ANY ns_t_any
+#define T_URI ns_t_uri
+#define T_CAA ns_t_caa
+#define T_AVC ns_t_avc
+#define T_TA ns_t_ta
+#define T_DLV ns_t_dlv
#define C_IN ns_c_in
#define C_CHAOS ns_c_chaos
diff --git a/include/dirent.h b/include/dirent.h
index 650ecf64..2d8fffb2 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -56,7 +56,7 @@ int getdents(int, struct dirent *, size_t);
int versionsort(const struct dirent **, const struct dirent **);
#endif
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define dirent64 dirent
#define readdir64 readdir
#define readdir64_r readdir_r
diff --git a/include/fcntl.h b/include/fcntl.h
index b664cdc4..515f255d 100644
--- a/include/fcntl.h
+++ b/include/fcntl.h
@@ -195,7 +195,7 @@ ssize_t tee(int, int, size_t, unsigned);
#define loff_t off_t
#endif
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define F_GETLK64 F_GETLK
#define F_SETLK64 F_SETLK
#define F_SETLKW64 F_SETLKW
diff --git a/include/ftw.h b/include/ftw.h
index b15c062a..d0445e8a 100644
--- a/include/ftw.h
+++ b/include/ftw.h
@@ -29,7 +29,7 @@ struct FTW {
int ftw(const char *, int (*)(const char *, const struct stat *, int), int);
int nftw(const char *, int (*)(const char *, const struct stat *, int, struct FTW *), int, int);
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define ftw64 ftw
#define nftw64 nftw
#endif
diff --git a/include/glob.h b/include/glob.h
index 4a562a20..fed06745 100644
--- a/include/glob.h
+++ b/include/glob.h
@@ -39,7 +39,7 @@ void globfree(glob_t *);
#define GLOB_NOMATCH 3
#define GLOB_NOSYS 4
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define glob64 glob
#define globfree64 globfree
#define glob64_t glob_t
diff --git a/include/netdb.h b/include/netdb.h
index d096c781..3af065e2 100644
--- a/include/netdb.h
+++ b/include/netdb.h
@@ -44,6 +44,7 @@ struct addrinfo {
#define EAI_NONAME -2
#define EAI_AGAIN -3
#define EAI_FAIL -4
+#define EAI_NODATA -5
#define EAI_FAMILY -6
#define EAI_SOCKTYPE -7
#define EAI_SERVICE -8
diff --git a/include/stdio.h b/include/stdio.h
index d1ed01f0..cb858618 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -205,7 +205,7 @@ typedef struct _IO_cookie_io_functions_t {
FILE *fopencookie(void *, const char *, cookie_io_functions_t);
#endif
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define tmpfile64 tmpfile
#define fopen64 fopen
#define freopen64 freopen
diff --git a/include/stdlib.h b/include/stdlib.h
index b507ca33..b117a452 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -163,7 +163,7 @@ double strtod_l(const char *__restrict, char **__restrict, struct __locale_struc
long double strtold_l(const char *__restrict, char **__restrict, struct __locale_struct *);
#endif
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define mkstemp64 mkstemp
#define mkostemp64 mkostemp
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
diff --git a/include/sys/mman.h b/include/sys/mman.h
index 80a3baae..3d5d0f9c 100644
--- a/include/sys/mman.h
+++ b/include/sys/mman.h
@@ -141,7 +141,7 @@ int mincore (void *, size_t, unsigned char *);
int shm_open (const char *, int, mode_t);
int shm_unlink (const char *);
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define mmap64 mmap
#define off64_t off_t
#endif
diff --git a/include/sys/resource.h b/include/sys/resource.h
index 3068328d..e8bfbe1f 100644
--- a/include/sys/resource.h
+++ b/include/sys/resource.h
@@ -95,7 +95,7 @@ int prlimit(pid_t, int, const struct rlimit *, struct rlimit *);
#define RLIM_NLIMITS RLIMIT_NLIMITS
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define RLIM64_INFINITY RLIM_INFINITY
#define RLIM64_SAVED_CUR RLIM_SAVED_CUR
#define RLIM64_SAVED_MAX RLIM_SAVED_MAX
diff --git a/include/sys/sendfile.h b/include/sys/sendfile.h
index e7570d8e..253a041b 100644
--- a/include/sys/sendfile.h
+++ b/include/sys/sendfile.h
@@ -10,7 +10,7 @@ extern "C" {
ssize_t sendfile(int, int, off_t *, size_t);
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define sendfile64 sendfile
#define off64_t off_t
#endif
diff --git a/include/sys/stat.h b/include/sys/stat.h
index 10d446c4..e6d0049c 100644
--- a/include/sys/stat.h
+++ b/include/sys/stat.h
@@ -98,7 +98,7 @@ int lchmod(const char *, mode_t);
#define S_IEXEC S_IXUSR
#endif
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define stat64 stat
#define fstat64 fstat
#define lstat64 lstat
diff --git a/include/sys/statfs.h b/include/sys/statfs.h
index 6f4c6230..7a2e11cd 100644
--- a/include/sys/statfs.h
+++ b/include/sys/statfs.h
@@ -18,7 +18,7 @@ typedef struct __fsid_t {
int statfs (const char *, struct statfs *);
int fstatfs (int, struct statfs *);
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define statfs64 statfs
#define fstatfs64 fstatfs
#define fsblkcnt64_t fsblkcnt_t
diff --git a/include/sys/statvfs.h b/include/sys/statvfs.h
index 793490b6..57a6b806 100644
--- a/include/sys/statvfs.h
+++ b/include/sys/statvfs.h
@@ -42,7 +42,7 @@ int fstatvfs (int, struct statvfs *);
#define ST_NODIRATIME 2048
#define ST_RELATIME 4096
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define statvfs64 statvfs
#define fstatvfs64 fstatvfs
#define fsblkcnt64_t fsblkcnt_t
diff --git a/include/sys/types.h b/include/sys/types.h
index 0c35541d..3363374f 100644
--- a/include/sys/types.h
+++ b/include/sys/types.h
@@ -71,7 +71,7 @@ typedef unsigned long long u_quad_t;
#include <sys/select.h>
#endif
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define blkcnt64_t blkcnt_t
#define fsblkcnt64_t fsblkcnt_t
#define fsfilcnt64_t fsfilcnt_t
diff --git a/include/sys/uio.h b/include/sys/uio.h
index 00f73a2f..90e5939e 100644
--- a/include/sys/uio.h
+++ b/include/sys/uio.h
@@ -29,7 +29,7 @@ ssize_t writev (int, const struct iovec *, int);
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
ssize_t preadv (int, const struct iovec *, int, off_t);
ssize_t pwritev (int, const struct iovec *, int, off_t);
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define preadv64 preadv
#define pwritev64 pwritev
#define off64_t off_t
diff --git a/include/unistd.h b/include/unistd.h
index 80be3b26..5bc7f798 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -198,7 +198,7 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
pid_t gettid(void);
#endif
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
#define lseek64 lseek
#define pread64 pread
#define pwrite64 pwrite
@@ -425,6 +425,8 @@ pid_t gettid(void);
#define _SC_XOPEN_STREAMS 246
#define _SC_THREAD_ROBUST_PRIO_INHERIT 247
#define _SC_THREAD_ROBUST_PRIO_PROTECT 248
+#define _SC_MINSIGSTKSZ 249
+#define _SC_SIGSTKSZ 250
#define _CS_PATH 0
#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1
diff --git a/ldso/dlstart.c b/ldso/dlstart.c
index 20d50f2c..259f5e18 100644
--- a/ldso/dlstart.c
+++ b/ldso/dlstart.c
@@ -140,6 +140,21 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
size_t *rel_addr = (void *)(base + rel[0]);
*rel_addr = base + rel[2];
}
+
+ rel = (void *)(base+dyn[DT_RELR]);
+ rel_size = dyn[DT_RELRSZ];
+ size_t *relr_addr = 0;
+ for (; rel_size; rel++, rel_size-=sizeof(size_t)) {
+ if ((rel[0]&1) == 0) {
+ relr_addr = (void *)(base + rel[0]);
+ *relr_addr++ += base;
+ } else {
+ for (size_t i=0, bitmap=rel[0]; bitmap>>=1; i++)
+ if (bitmap&1)
+ relr_addr[i] += base;
+ relr_addr += 8*sizeof(size_t)-1;
+ }
+ }
#endif
stage2_func dls2;
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index fd09ca69..7b47b163 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -337,6 +337,39 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
return find_sym2(dso, s, need_def, 0);
}
+static struct symdef get_lfs64(const char *name)
+{
+ static const char *p, lfs64_list[] =
+ "aio_cancel\0aio_error\0aio_fsync\0aio_read\0aio_return\0"
+ "aio_suspend\0aio_write\0alphasort\0creat\0fallocate\0"
+ "fgetpos\0fopen\0freopen\0fseeko\0fsetpos\0fstat\0"
+ "fstatat\0fstatfs\0fstatvfs\0ftello\0ftruncate\0ftw\0"
+ "getdents\0getrlimit\0glob\0globfree\0lio_listio\0"
+ "lockf\0lseek\0lstat\0mkostemp\0mkostemps\0mkstemp\0"
+ "mkstemps\0mmap\0nftw\0open\0openat\0posix_fadvise\0"
+ "posix_fallocate\0pread\0preadv\0prlimit\0pwrite\0"
+ "pwritev\0readdir\0scandir\0sendfile\0setrlimit\0"
+ "stat\0statfs\0statvfs\0tmpfile\0truncate\0versionsort\0"
+ "__fxstat\0__fxstatat\0__lxstat\0__xstat\0";
+ size_t l;
+ char buf[16];
+ for (l=0; name[l]; l++) {
+ if (l >= sizeof buf) goto nomatch;
+ buf[l] = name[l];
+ }
+ if (!strcmp(name, "readdir64_r"))
+ return find_sym(&ldso, "readdir_r", 1);
+ if (l<2 || name[l-2]!='6' || name[l-1]!='4')
+ goto nomatch;
+ buf[l-=2] = 0;
+ for (p=lfs64_list; *p; p++) {
+ if (!strcmp(buf, p)) return find_sym(&ldso, buf, 1);
+ while (*p) p++;
+ }
+nomatch:
+ return (struct symdef){ 0 };
+}
+
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
{
unsigned char *base = dso->base;
@@ -390,6 +423,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
def = (sym->st_info>>4) == STB_LOCAL
? (struct symdef){ .dso = dso, .sym = sym }
: find_sym(ctx, name, type==REL_PLT);
+ if (!def.sym) def = get_lfs64(name);
if (!def.sym && (sym->st_shndx != SHN_UNDEF
|| sym->st_info>>4 != STB_WEAK)) {
if (dso->lazy && (type==REL_PLT || type==REL_GOT)) {
@@ -886,7 +920,7 @@ static int fixup_rpath(struct dso *p, char *buf, size_t buf_size)
case ENOENT:
case ENOTDIR:
case EACCES:
- break;
+ return 0;
default:
return -1;
}
diff --git a/src/aio/aio.c b/src/aio/aio.c
index a1a3e791..d7e063bf 100644
--- a/src/aio/aio.c
+++ b/src/aio/aio.c
@@ -82,6 +82,8 @@ static size_t io_thread_stack_size;
static struct aio_queue *__aio_get_queue(int fd, int need)
{
+ sigset_t allmask, origmask;
+ int masked = 0;
if (fd < 0) {
errno = EBADF;
return 0;
@@ -93,6 +95,9 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
if ((!map || !map[a] || !map[a][b] || !map[a][b][c] || !(q=map[a][b][c][d])) && need) {
pthread_rwlock_unlock(&maplock);
if (fcntl(fd, F_GETFD) < 0) return 0;
+ sigfillset(&allmask);
+ masked = 1;
+ pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
pthread_rwlock_wrlock(&maplock);
if (!io_thread_stack_size) {
unsigned long val = __getauxval(AT_MINSIGSTKSZ);
@@ -119,6 +124,7 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
if (q) pthread_mutex_lock(&q->lock);
out:
pthread_rwlock_unlock(&maplock);
+ if (masked) pthread_sigmask(SIG_SETMASK, &origmask, 0);
return q;
}
@@ -401,18 +407,26 @@ void __aio_atfork(int who)
if (who<0) {
pthread_rwlock_rdlock(&maplock);
return;
+ } else if (!who) {
+ pthread_rwlock_unlock(&maplock);
+ return;
}
- if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++)
+ aio_fd_cnt = 0;
+ if (pthread_rwlock_tryrdlock(&maplock)) {
+ /* Obtaining lock may fail if _Fork was called nor via
+ * fork. In this case, no further aio is possible from
+ * child and we can just null out map so __aio_close
+ * does not attempt to do anything. */
+ map = 0;
+ return;
+ }
+ if (map) for (int a=0; a<(-1U/2+1)>>24; a++)
if (map[a]) for (int b=0; b<256; b++)
if (map[a][b]) for (int c=0; c<256; c++)
if (map[a][b][c]) for (int d=0; d<256; d++)
map[a][b][c][d] = 0;
- pthread_rwlock_unlock(&maplock);
+ /* Re-initialize the rwlock rather than unlocking since there
+ * may have been more than one reference on it in the parent.
+ * We are not a lock holder anyway; the thread in the parent was. */
+ pthread_rwlock_init(&maplock, 0);
}
-
-weak_alias(aio_cancel, aio_cancel64);
-weak_alias(aio_error, aio_error64);
-weak_alias(aio_fsync, aio_fsync64);
-weak_alias(aio_read, aio_read64);
-weak_alias(aio_write, aio_write64);
-weak_alias(aio_return, aio_return64);
diff --git a/src/aio/aio_suspend.c b/src/aio/aio_suspend.c
index 1c1060e3..1f0c9aaa 100644
--- a/src/aio/aio_suspend.c
+++ b/src/aio/aio_suspend.c
@@ -9,7 +9,7 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
{
int i, tid = 0, ret, expect = 0;
struct timespec at;
- volatile int dummy_fut, *pfut;
+ volatile int dummy_fut = 0, *pfut;
int nzcnt = 0;
const struct aiocb *cb = 0;
@@ -73,7 +73,3 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
}
}
}
-
-#if !_REDIR_TIME64
-weak_alias(aio_suspend, aio_suspend64);
-#endif
diff --git a/src/aio/lio_listio.c b/src/aio/lio_listio.c
index 0799c15d..a672812f 100644
--- a/src/aio/lio_listio.c
+++ b/src/aio/lio_listio.c
@@ -139,5 +139,3 @@ int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, st
return 0;
}
-
-weak_alias(lio_listio, lio_listio64);
diff --git a/src/conf/sysconf.c b/src/conf/sysconf.c
index 3baaed32..60d3e745 100644
--- a/src/conf/sysconf.c
+++ b/src/conf/sysconf.c
@@ -4,6 +4,7 @@
#include <sys/resource.h>
#include <signal.h>
#include <sys/sysinfo.h>
+#include <sys/auxv.h>
#include "syscall.h"
#include "libc.h"
@@ -19,6 +20,8 @@
#define JT_AVPHYS_PAGES JT(9)
#define JT_ZERO JT(10)
#define JT_DELAYTIMER_MAX JT(11)
+#define JT_MINSIGSTKSZ JT(12)
+#define JT_SIGSTKSZ JT(13)
#define RLIM(x) (-32768|(RLIMIT_ ## x))
@@ -165,6 +168,9 @@ long sysconf(int name)
[_SC_XOPEN_STREAMS] = JT_ZERO,
[_SC_THREAD_ROBUST_PRIO_INHERIT] = -1,
[_SC_THREAD_ROBUST_PRIO_PROTECT] = -1,
+
+ [_SC_MINSIGSTKSZ] = JT_MINSIGSTKSZ,
+ [_SC_SIGSTKSZ] = JT_SIGSTKSZ,
};
if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) {
@@ -212,6 +218,13 @@ long sysconf(int name)
mem *= si.mem_unit;
mem /= PAGE_SIZE;
return (mem > LONG_MAX) ? LONG_MAX : mem;
+ case JT_MINSIGSTKSZ & 255:
+ case JT_SIGSTKSZ & 255: ;
+ long val = __getauxval(AT_MINSIGSTKSZ);
+ if (val < MINSIGSTKSZ) val = MINSIGSTKSZ;
+ if (values[name] == JT_SIGSTKSZ)
+ val += SIGSTKSZ - MINSIGSTKSZ;
+ return val;
case JT_ZERO & 255:
return 0;
}
diff --git a/src/dirent/alphasort.c b/src/dirent/alphasort.c
index bee672eb..ab2624e2 100644
--- a/src/dirent/alphasort.c
+++ b/src/dirent/alphasort.c
@@ -5,5 +5,3 @@ int alphasort(const struct dirent **a, const struct dirent **b)
{
return strcoll((*a)->d_name, (*b)->d_name);
}
-
-weak_alias(alphasort, alphasort64);
diff --git a/src/dirent/readdir.c b/src/dirent/readdir.c
index 569fc705..5a03b363 100644
--- a/src/dirent/readdir.c
+++ b/src/dirent/readdir.c
@@ -25,5 +25,3 @@ struct dirent *readdir(DIR *dir)
dir->tell = de->d_off;
return de;
}
-
-weak_alias(readdir, readdir64);
diff --git a/src/dirent/readdir_r.c b/src/dirent/readdir_r.c
index e2a818f3..0d5de5f5 100644
--- a/src/dirent/readdir_r.c
+++ b/src/dirent/readdir_r.c
@@ -25,5 +25,3 @@ int readdir_r(DIR *restrict dir, struct dirent *restrict buf, struct dirent **re
*result = buf;
return 0;
}
-
-weak_alias(readdir_r, readdir64_r);
diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c
index 7ee195dd..7456b9b8 100644
--- a/src/dirent/scandir.c
+++ b/src/dirent/scandir.c
@@ -43,5 +43,3 @@ int scandir(const char *path, struct dirent ***res,
*res = names;
return cnt;
}
-
-weak_alias(scandir, scandir64);
diff --git a/src/dirent/versionsort.c b/src/dirent/versionsort.c
index d4c48923..97696105 100644
--- a/src/dirent/versionsort.c
+++ b/src/dirent/versionsort.c
@@ -6,6 +6,3 @@ int versionsort(const struct dirent **a, const struct dirent **b)
{
return strverscmp((*a)->d_name, (*b)->d_name);
}
-
-#undef versionsort64
-weak_alias(versionsort, versionsort64);
diff --git a/src/fcntl/creat.c b/src/fcntl/creat.c
index 8f8aab64..c9c43910 100644
--- a/src/fcntl/creat.c
+++ b/src/fcntl/creat.c
@@ -4,5 +4,3 @@ int creat(const char *filename, mode_t mode)
{
return open(filename, O_CREAT|O_WRONLY|O_TRUNC, mode);
}
-
-weak_alias(creat, creat64);
diff --git a/src/fcntl/open.c b/src/fcntl/open.c
index 1d817a2d..4c3c8275 100644
--- a/src/fcntl/open.c
+++ b/src/fcntl/open.c
@@ -19,5 +19,3 @@ int open(const char *filename, int flags, ...)
return __syscall_ret(fd);
}
-
-weak_alias(open, open64);
diff --git a/src/fcntl/openat.c b/src/fcntl/openat.c
index ad165ec3..83a9e0d0 100644
--- a/src/fcntl/openat.c
+++ b/src/fcntl/openat.c
@@ -15,5 +15,3 @@ int openat(int fd, const char *filename, int flags, ...)
return syscall_cp(SYS_openat, fd, filename, flags|O_LARGEFILE, mode);
}
-
-weak_alias(openat, openat64);
diff --git a/src/fcntl/posix_fadvise.c b/src/fcntl/posix_fadvise.c
index 75b8e1ae..07346d21 100644
--- a/src/fcntl/posix_fadvise.c
+++ b/src/fcntl/posix_fadvise.c
@@ -14,5 +14,3 @@ int posix_fadvise(int fd, off_t base, off_t len, int advice)
__SYSCALL_LL_E(len), advice);
#endif
}
-
-weak_alias(posix_fadvise, posix_fadvise64);
diff --git a/src/fcntl/posix_fallocate.c b/src/fcntl/posix_fallocate.c
index c57a24ae..80a65cbf 100644
--- a/src/fcntl/posix_fallocate.c
+++ b/src/fcntl/posix_fallocate.c
@@ -6,5 +6,3 @@ int posix_fallocate(int fd, off_t base, off_t len)
return -__syscall(SYS_fallocate, fd, 0, __SYSCALL_LL_E(base),
__SYSCALL_LL_E(len));
}
-
-weak_alias(posix_fallocate, posix_fallocate64);
diff --git a/src/internal/fork_impl.h b/src/internal/fork_impl.h
index 5892c13b..354e733b 100644
--- a/src/internal/fork_impl.h
+++ b/src/internal/fork_impl.h
@@ -2,7 +2,6 @@
extern hidden volatile int *const __at_quick_exit_lockptr;
extern hidden volatile int *const __atexit_lockptr;
-extern hidden volatile int *const __dlerror_lockptr;
extern hidden volatile int *const __gettext_lockptr;
extern hidden volatile int *const __locale_lockptr;
extern hidden volatile int *const __random_lockptr;
@@ -17,3 +16,4 @@ extern hidden volatile int *const __vmlock_lockptr;
hidden void __malloc_atfork(int);
hidden void __ldso_atfork(int);
+hidden void __pthread_key_atfork(int);
diff --git a/src/ldso/dlerror.c b/src/ldso/dlerror.c
index afe59253..dae0f3a9 100644
--- a/src/ldso/dlerror.c
+++ b/src/ldso/dlerror.c
@@ -3,8 +3,7 @@
#include <stdarg.h>
#include "pthread_impl.h"
#include "dynlink.h"
-#include "lock.h"
-#include "fork_impl.h"
+#include "atomic.h"
#define malloc __libc_malloc
#define calloc __libc_calloc
@@ -23,28 +22,31 @@ char *dlerror()
return s;
}
-static volatile int freebuf_queue_lock[1];
-static void **freebuf_queue;
-volatile int *const __dlerror_lockptr = freebuf_queue_lock;
+/* Atomic singly-linked list, used to store list of thread-local dlerror
+ * buffers for deferred free. They cannot be freed at thread exit time
+ * because, by the time it's known they can be freed, the exiting thread
+ * is in a highly restrictive context where it cannot call (even the
+ * libc-internal) free. It also can't take locks; thus the atomic list. */
+
+static void *volatile freebuf_queue;
void __dl_thread_cleanup(void)
{
pthread_t self = __pthread_self();
- if (self->dlerror_buf && self->dlerror_buf != (void *)-1) {
- LOCK(freebuf_queue_lock);
- void **p = (void **)self->dlerror_buf;
- *p = freebuf_queue;
- freebuf_queue = p;
- UNLOCK(freebuf_queue_lock);
- }
+ if (!self->dlerror_buf || self->dlerror_buf == (void *)-1)
+ return;
+ void *h;
+ do {
+ h = freebuf_queue;
+ *(void **)self->dlerror_buf = h;
+ } while (a_cas_p(&freebuf_queue, h, self->dlerror_buf) != h);
}
hidden void __dl_vseterr(const char *fmt, va_list ap)
{
- LOCK(freebuf_queue_lock);
- void **q = freebuf_queue;
- freebuf_queue = 0;
- UNLOCK(freebuf_queue_lock);
+ void **q;
+ do q = freebuf_queue;
+ while (q && a_cas_p(&freebuf_queue, q, 0) != q);
while (q) {
void **p = *q;
diff --git a/src/legacy/ftw.c b/src/legacy/ftw.c
index 506bd29c..e757fc6f 100644
--- a/src/legacy/ftw.c
+++ b/src/legacy/ftw.c
@@ -7,5 +7,3 @@ int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int
* actually undefined, but works on all real-world machines. */
return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS);
}
-
-weak_alias(ftw, ftw64);
diff --git a/src/linux/epoll.c b/src/linux/epoll.c
index 93baa814..e56e8f4c 100644
--- a/src/linux/epoll.c
+++ b/src/linux/epoll.c
@@ -5,6 +5,7 @@
int epoll_create(int size)
{
+ if (size<=0) return __syscall_ret(-EINVAL);
return epoll_create1(0);
}
diff --git a/src/linux/fallocate.c b/src/linux/fallocate.c
index 7d68bc8f..9146350e 100644
--- a/src/linux/fallocate.c
+++ b/src/linux/fallocate.c
@@ -7,6 +7,3 @@ int fallocate(int fd, int mode, off_t base, off_t len)
return syscall(SYS_fallocate, fd, mode, __SYSCALL_LL_E(base),
__SYSCALL_LL_E(len));
}
-
-#undef fallocate64
-weak_alias(fallocate, fallocate64);
diff --git a/src/linux/getdents.c b/src/linux/getdents.c
index 796c1e5c..97f76e14 100644
--- a/src/linux/getdents.c
+++ b/src/linux/getdents.c
@@ -8,5 +8,3 @@ int getdents(int fd, struct dirent *buf, size_t len)
if (len>INT_MAX) len = INT_MAX;
return syscall(SYS_getdents, fd, buf, len);
}
-
-weak_alias(getdents, getdents64);
diff --git a/src/linux/membarrier.c b/src/linux/membarrier.c
index 343f7360..f64fe7e1 100644
--- a/src/linux/membarrier.c
+++ b/src/linux/membarrier.c
@@ -35,7 +35,7 @@ int __membarrier(int cmd, int flags)
__tl_lock();
sem_init(&barrier_sem, 0, 0);
struct sigaction sa = {
- .sa_flags = SA_RESTART,
+ .sa_flags = SA_RESTART | SA_ONSTACK,
.sa_handler = bcast_barrier
};
memset(&sa.sa_mask, -1, sizeof sa.sa_mask);
diff --git a/src/linux/prlimit.c b/src/linux/prlimit.c
index 3df9ffba..fcf45aab 100644
--- a/src/linux/prlimit.c
+++ b/src/linux/prlimit.c
@@ -21,6 +21,3 @@ int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlim
}
return r;
}
-
-#undef prlimit64
-weak_alias(prlimit, prlimit64);
diff --git a/src/linux/sendfile.c b/src/linux/sendfile.c
index 9afe6dd6..fc1577d3 100644
--- a/src/linux/sendfile.c
+++ b/src/linux/sendfile.c
@@ -5,5 +5,3 @@ ssize_t sendfile(int out_fd, int in_fd, off_t *ofs, size_t count)
{
return syscall(SYS_sendfile, out_fd, in_fd, ofs, count);
}
-
-weak_alias(sendfile, sendfile64);
diff --git a/src/malloc/mallocng/free.c b/src/malloc/mallocng/free.c
index 418a085c..43f32aad 100644
--- a/src/malloc/mallocng/free.c
+++ b/src/malloc/mallocng/free.c
@@ -119,7 +119,7 @@ void free(void *p)
if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) {
unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1));
size_t len = (end-base) & -PGSZ;
- if (len) {
+ if (len && USE_MADV_FREE) {
int e = errno;
madvise(base, len, MADV_FREE);
errno = e;
diff --git a/src/malloc/mallocng/glue.h b/src/malloc/mallocng/glue.h
index 151c48b8..77f4c812 100644
--- a/src/malloc/mallocng/glue.h
+++ b/src/malloc/mallocng/glue.h
@@ -24,6 +24,8 @@
#define realloc __libc_realloc
#define free __libc_free
+#define USE_MADV_FREE 0
+
#if USE_REAL_ASSERT
#include <assert.h>
#else
diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c
index bf676307..a5558d81 100644
--- a/src/misc/getrlimit.c
+++ b/src/misc/getrlimit.c
@@ -26,5 +26,3 @@ int getrlimit(int resource, struct rlimit *rlim)
return ret;
#endif
}
-
-weak_alias(getrlimit, getrlimit64);
diff --git a/src/misc/lockf.c b/src/misc/lockf.c
index 16a80bec..0162442b 100644
--- a/src/misc/lockf.c
+++ b/src/misc/lockf.c
@@ -28,5 +28,3 @@ int lockf(int fd, int op, off_t size)
errno = EINVAL;
return -1;
}
-
-weak_alias(lockf, lockf64);
diff --git a/src/misc/nftw.c b/src/misc/nftw.c
index 8dcff7fe..fcd25a73 100644
--- a/src/misc/nftw.c
+++ b/src/misc/nftw.c
@@ -138,5 +138,3 @@ int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, str
pthread_setcancelstate(cs, 0);
return r;
}
-
-weak_alias(nftw, nftw64);
diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c
index 5b713cf3..edb413fa 100644
--- a/src/misc/setrlimit.c
+++ b/src/misc/setrlimit.c
@@ -49,5 +49,3 @@ int setrlimit(int resource, const struct rlimit *rlim)
return __syscall_ret(ret);
#endif
}
-
-weak_alias(setrlimit, setrlimit64);
diff --git a/src/mman/mmap.c b/src/mman/mmap.c
index eff88d82..43e5e029 100644
--- a/src/mman/mmap.c
+++ b/src/mman/mmap.c
@@ -37,5 +37,3 @@ void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
}
weak_alias(__mmap, mmap);
-
-weak_alias(mmap, mmap64);
diff --git a/src/network/gai_strerror.c b/src/network/gai_strerror.c
index 9596580e..56b71503 100644
--- a/src/network/gai_strerror.c
+++ b/src/network/gai_strerror.c
@@ -6,7 +6,7 @@ static const char msgs[] =
"Name does not resolve\0"
"Try again\0"
"Non-recoverable error\0"
- "Unknown error\0"
+ "Name has no usable address\0"
"Unrecognized address family or invalid length\0"
"Unrecognized socket type\0"
"Unrecognized service\0"
diff --git a/src/network/getaddrinfo.c b/src/network/getaddrinfo.c
index 9df045f6..64ad259a 100644
--- a/src/network/getaddrinfo.c
+++ b/src/network/getaddrinfo.c
@@ -16,6 +16,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
char canon[256], *outcanon;
int nservs, naddrs, nais, canon_len, i, j, k;
int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0;
+ int no_family = 0;
struct aibuf *out;
if (!host && !serv) return EAI_NONAME;
@@ -82,7 +83,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
default:
return EAI_SYSTEM;
}
- if (family == tf[i]) return EAI_NONAME;
+ if (family == tf[i]) no_family = 1;
family = tf[1-i];
}
}
@@ -93,6 +94,8 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
naddrs = __lookup_name(addrs, canon, host, family, flags);
if (naddrs < 0) return naddrs;
+ if (no_family) return EAI_NODATA;
+
nais = nservs * naddrs;
canon_len = strlen(canon);
out = calloc(1, nais * sizeof(*out) + canon_len + 1);
diff --git a/src/network/gethostbyaddr.c b/src/network/gethostbyaddr.c
index 598e2241..c3cacaac 100644
--- a/src/network/gethostbyaddr.c
+++ b/src/network/gethostbyaddr.c
@@ -20,5 +20,5 @@ struct hostent *gethostbyaddr(const void *a, socklen_t l, int af)
err = gethostbyaddr_r(a, l, af, h,
(void *)(h+1), size-sizeof *h, &res, &h_errno);
} while (err == ERANGE);
- return err ? 0 : h;
+ return res;
}
diff --git a/src/network/gethostbyaddr_r.c b/src/network/gethostbyaddr_r.c
index 0f1e61aa..ceaf3935 100644
--- a/src/network/gethostbyaddr_r.c
+++ b/src/network/gethostbyaddr_r.c
@@ -54,10 +54,11 @@ int gethostbyaddr_r(const void *a, socklen_t l, int af,
case EAI_OVERFLOW:
return ERANGE;
default:
- case EAI_MEMORY:
- case EAI_SYSTEM:
case EAI_FAIL:
*err = NO_RECOVERY;
+ return EBADMSG;
+ case EAI_SYSTEM:
+ *err = NO_RECOVERY;
return errno;
case 0:
break;
diff --git a/src/network/gethostbyname2.c b/src/network/gethostbyname2.c
index dc9d6621..bd0da7f8 100644
--- a/src/network/gethostbyname2.c
+++ b/src/network/gethostbyname2.c
@@ -21,5 +21,5 @@ struct hostent *gethostbyname2(const char *name, int af)
err = gethostbyname2_r(name, af, h,
(void *)(h+1), size-sizeof *h, &res, &h_errno);
} while (err == ERANGE);
- return err ? 0 : h;
+ return res;
}
diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c
index fc894877..a5eb67fe 100644
--- a/src/network/gethostbyname2_r.c
+++ b/src/network/gethostbyname2_r.c
@@ -22,7 +22,10 @@ int gethostbyname2_r(const char *name, int af,
if (cnt<0) switch (cnt) {
case EAI_NONAME:
*err = HOST_NOT_FOUND;
- return ENOENT;
+ return 0;
+ case EAI_NODATA:
+ *err = NO_DATA;
+ return 0;
case EAI_AGAIN:
*err = TRY_AGAIN;
return EAGAIN;
@@ -30,7 +33,6 @@ int gethostbyname2_r(const char *name, int af,
case EAI_FAIL:
*err = NO_RECOVERY;
return EBADMSG;
- case EAI_MEMORY:
case EAI_SYSTEM:
*err = NO_RECOVERY;
return errno;
diff --git a/src/network/lookup_ipliteral.c b/src/network/lookup_ipliteral.c
index 2fddab73..1e766206 100644
--- a/src/network/lookup_ipliteral.c
+++ b/src/network/lookup_ipliteral.c
@@ -15,7 +15,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil
struct in6_addr a6;
if (__inet_aton(name, &a4) > 0) {
if (family == AF_INET6) /* wrong family */
- return EAI_NONAME;
+ return EAI_NODATA;
memcpy(&buf[0].addr, &a4, sizeof a4);
buf[0].family = AF_INET;
buf[0].scopeid = 0;
@@ -34,7 +34,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil
if (inet_pton(AF_INET6, name, &a6) <= 0)
return 0;
if (family == AF_INET) /* wrong family */
- return EAI_NONAME;
+ return EAI_NODATA;
memcpy(&buf[0].addr, &a6, sizeof a6);
buf[0].family = AF_INET6;
diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c
index b5232ce8..5f6867cb 100644
--- a/src/network/lookup_name.c
+++ b/src/network/lookup_name.c
@@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
case 0:
continue;
default:
- badfam = EAI_NONAME;
+ badfam = EAI_NODATA;
break;
}
@@ -102,45 +102,50 @@ struct dpc_ctx {
struct address *addrs;
char *canon;
int cnt;
+ int rrtype;
};
#define RR_A 1
#define RR_CNAME 5
#define RR_AAAA 28
+#define ABUF_SIZE 768
+
static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet)
{
char tmp[256];
+ int family;
struct dpc_ctx *ctx = c;
- if (ctx->cnt >= MAXADDRS) return -1;
+ if (rr == RR_CNAME) {
+ if (__dn_expand(packet, (const unsigned char *)packet + ABUF_SIZE,
+ data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
+ strcpy(ctx->canon, tmp);
+ return 0;
+ }
+ if (ctx->cnt >= MAXADDRS) return 0;
+ if (rr != ctx->rrtype) return 0;
switch (rr) {
case RR_A:
if (len != 4) return -1;
- ctx->addrs[ctx->cnt].family = AF_INET;
- ctx->addrs[ctx->cnt].scopeid = 0;
- memcpy(ctx->addrs[ctx->cnt++].addr, data, 4);
+ family = AF_INET;
break;
case RR_AAAA:
if (len != 16) return -1;
- ctx->addrs[ctx->cnt].family = AF_INET6;
- ctx->addrs[ctx->cnt].scopeid = 0;
- memcpy(ctx->addrs[ctx->cnt++].addr, data, 16);
- break;
- case RR_CNAME:
- if (__dn_expand(packet, (const unsigned char *)packet + 512,
- data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
- strcpy(ctx->canon, tmp);
+ family = AF_INET6;
break;
}
+ ctx->addrs[ctx->cnt].family = family;
+ ctx->addrs[ctx->cnt].scopeid = 0;
+ memcpy(ctx->addrs[ctx->cnt++].addr, data, len);
return 0;
}
static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, const struct resolvconf *conf)
{
- unsigned char qbuf[2][280], abuf[2][512];
+ unsigned char qbuf[2][280], abuf[2][ABUF_SIZE];
const unsigned char *qp[2] = { qbuf[0], qbuf[1] };
unsigned char *ap[2] = { abuf[0], abuf[1] };
- int qlens[2], alens[2];
+ int qlens[2], alens[2], qtypes[2];
int i, nq = 0;
struct dpc_ctx ctx = { .addrs = buf, .canon = canon };
static const struct { int af; int rr; } afrr[2] = {
@@ -153,7 +158,8 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
qlens[nq] = __res_mkquery(0, name, 1, afrr[i].rr,
0, 0, 0, qbuf[nq], sizeof *qbuf);
if (qlens[nq] == -1)
- return EAI_NONAME;
+ return 0;
+ qtypes[nq] = afrr[i].rr;
qbuf[nq][3] = 0; /* don't need AD flag */
/* Ensure query IDs are distinct. */
if (nq && qbuf[nq][0] == qbuf[0][0])
@@ -171,11 +177,13 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
if ((abuf[i][3] & 15) != 0) return EAI_FAIL;
}
- for (i=0; i<nq; i++)
+ for (i=nq-1; i>=0; i--) {
+ ctx.rrtype = qtypes[i];
__dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx);
+ }
if (ctx.cnt) return ctx.cnt;
- return EAI_NONAME;
+ return EAI_NODATA;
}
static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
diff --git a/src/network/res_mkquery.c b/src/network/res_mkquery.c
index 33f50cb9..614bf786 100644
--- a/src/network/res_mkquery.c
+++ b/src/network/res_mkquery.c
@@ -13,6 +13,7 @@ int __res_mkquery(int op, const char *dname, int class, int type,
int n;
if (l && dname[l-1]=='.') l--;
+ if (l && dname[l-1]=='.') return -1;
n = 17+l+!!l;
if (l>253 || buflen<n || op>15u || class>255u || type>255u)
return -1;
diff --git a/src/network/res_msend.c b/src/network/res_msend.c
index 3e018009..11c6aa0e 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -1,5 +1,6 @@
#include <sys/socket.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdint.h>
@@ -16,7 +17,9 @@
static void cleanup(void *p)
{
- __syscall(SYS_close, (intptr_t)p);
+ struct pollfd *pfd = p;
+ for (int i=0; pfd[i].fd >= -1; i++)
+ if (pfd[i].fd >= 0) __syscall(SYS_close, pfd[i].fd);
}
static unsigned long mtime()
@@ -27,6 +30,51 @@ static unsigned long mtime()
+ ts.tv_nsec / 1000000;
}
+static int start_tcp(struct pollfd *pfd, int family, const void *sa, socklen_t sl, const unsigned char *q, int ql)
+{
+ struct msghdr mh = {
+ .msg_name = (void *)sa,
+ .msg_namelen = sl,
+ .msg_iovlen = 2,
+ .msg_iov = (struct iovec [2]){
+ { .iov_base = (uint8_t[]){ ql>>8, ql }, .iov_len = 2 },
+ { .iov_base = (void *)q, .iov_len = ql } }
+ };
+ int r;
+ int fd = socket(family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+ pfd->fd = fd;
+ pfd->events = POLLOUT;
+ if (!setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+ &(int){1}, sizeof(int))) {
+ r = sendmsg(fd, &mh, MSG_FASTOPEN|MSG_NOSIGNAL);
+ if (r == ql+2) pfd->events = POLLIN;
+ if (r >= 0) return r;
+ if (errno == EINPROGRESS) return 0;
+ }
+ r = connect(fd, sa, sl);
+ if (!r || errno == EINPROGRESS) return 0;
+ close(fd);
+ pfd->fd = -1;
+ return -1;
+}
+
+static void step_mh(struct msghdr *mh, size_t n)
+{
+ /* Adjust iovec in msghdr to skip first n bytes. */
+ while (mh->msg_iovlen && n >= mh->msg_iov->iov_len) {
+ n -= mh->msg_iov->iov_len;
+ mh->msg_iov++;
+ mh->msg_iovlen--;
+ }
+ if (!mh->msg_iovlen) return;
+ mh->msg_iov->iov_base = (char *)mh->msg_iov->iov_base + n;
+ mh->msg_iov->iov_len -= n;
+}
+
+/* Internal contract for __res_msend[_rc]: asize must be >=512, nqueries
+ * must be sufficiently small to be safe as VLA size. In practice it's
+ * either 1 or 2, anyway. */
+
int __res_msend_rc(int nqueries, const unsigned char *const *queries,
const int *qlens, unsigned char *const *answers, int *alens, int asize,
const struct resolvconf *conf)
@@ -44,7 +92,10 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
int next;
int i, j;
int cs;
- struct pollfd pfd;
+ struct pollfd pfd[nqueries+2];
+ int qpos[nqueries], apos[nqueries];
+ unsigned char alen_buf[nqueries][2];
+ int r;
unsigned long t0, t1, t2;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
@@ -68,14 +119,20 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
}
/* Get local address and open/bind a socket */
- sa.sin.sin_family = family;
fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
/* Handle case where system lacks IPv6 support */
if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
+ for (i=0; i<nns && conf->ns[nns].family == AF_INET6; i++);
+ if (i==nns) {
+ pthread_setcancelstate(cs, 0);
+ return -1;
+ }
fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
family = AF_INET;
+ sl = sizeof sa.sin;
}
+ sa.sin.sin_family = family;
if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) {
if (fd >= 0) close(fd);
pthread_setcancelstate(cs, 0);
@@ -86,7 +143,12 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
* yield either no reply (indicated by zero length) or an answer
* packet which is up to the caller to interpret. */
- pthread_cleanup_push(cleanup, (void *)(intptr_t)fd);
+ for (i=0; i<nqueries; i++) pfd[i].fd = -1;
+ pfd[nqueries].fd = fd;
+ pfd[nqueries].events = POLLIN;
+ pfd[nqueries+1].fd = -2;
+
+ pthread_cleanup_push(cleanup, pfd);
pthread_setcancelstate(cs, 0);
/* Convert any IPv4 addresses in a mixed environment to v4-mapped */
@@ -106,14 +168,17 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
memset(alens, 0, sizeof *alens * nqueries);
- pfd.fd = fd;
- pfd.events = POLLIN;
retry_interval = timeout / attempts;
next = 0;
t0 = t2 = mtime();
t1 = t2 - retry_interval;
for (; t2-t0 < timeout; t2=mtime()) {
+ /* This is the loop exit condition: that all queries
+ * have an accepted answer. */
+ for (i=0; i<nqueries && alens[i]>0; i++);
+ if (i==nqueries) break;
+
if (t2-t1 >= retry_interval) {
/* Query all configured namservers in parallel */
for (i=0; i<nqueries; i++)
@@ -127,10 +192,20 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
}
/* Wait for a response, or until time to retry */
- if (poll(&pfd, 1, t1+retry_interval-t2) <= 0) continue;
+ if (poll(pfd, nqueries+1, t1+retry_interval-t2) <= 0) continue;
- while ((rlen = recvfrom(fd, answers[next], asize, 0,
- (void *)&sa, (socklen_t[1]){sl})) >= 0) {
+ while (next < nqueries) {
+ struct msghdr mh = {
+ .msg_name = (void *)&sa,
+ .msg_namelen = sl,
+ .msg_iovlen = 1,
+ .msg_iov = (struct iovec []){
+ { .iov_base = (void *)answers[next],
+ .iov_len = asize }
+ }
+ };
+ rlen = recvmsg(fd, &mh, 0);
+ if (rlen < 0) break;
/* Ignore non-identifiable packets */
if (rlen < 4) continue;
@@ -170,12 +245,72 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
else
memcpy(answers[i], answers[next], rlen);
- if (next == nqueries) goto out;
+ /* Ignore further UDP if all slots full or TCP-mode */
+ if (next == nqueries) pfd[nqueries].events = 0;
+
+ /* If answer is truncated (TC bit), fallback to TCP */
+ if ((answers[i][2] & 2) || (mh.msg_flags & MSG_TRUNC)) {
+ alens[i] = -1;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
+ r = start_tcp(pfd+i, family, ns+j, sl, queries[i], qlens[i]);
+ pthread_setcancelstate(cs, 0);
+ if (r >= 0) {
+ qpos[i] = r;
+ apos[i] = 0;
+ }
+ continue;
+ }
+ }
+
+ for (i=0; i<nqueries; i++) if (pfd[i].revents & POLLOUT) {
+ struct msghdr mh = {
+ .msg_iovlen = 2,
+ .msg_iov = (struct iovec [2]){
+ { .iov_base = (uint8_t[]){ qlens[i]>>8, qlens[i] }, .iov_len = 2 },
+ { .iov_base = (void *)queries[i], .iov_len = qlens[i] } }
+ };
+ step_mh(&mh, qpos[i]);
+ r = sendmsg(pfd[i].fd, &mh, MSG_NOSIGNAL);
+ if (r < 0) goto out;
+ qpos[i] += r;
+ if (qpos[i] == qlens[i]+2)
+ pfd[i].events = POLLIN;
+ }
+
+ for (i=0; i<nqueries; i++) if (pfd[i].revents & POLLIN) {
+ struct msghdr mh = {
+ .msg_iovlen = 2,
+ .msg_iov = (struct iovec [2]){
+ { .iov_base = alen_buf[i], .iov_len = 2 },
+ { .iov_base = answers[i], .iov_len = asize } }
+ };
+ step_mh(&mh, apos[i]);
+ r = recvmsg(pfd[i].fd, &mh, 0);
+ if (r < 0) goto out;
+ apos[i] += r;
+ if (apos[i] < 2) continue;
+ int alen = alen_buf[i][0]*256 + alen_buf[i][1];
+ if (alen < 13) goto out;
+ if (apos[i] < alen+2 && apos[i] < asize+2)
+ continue;
+ int rcode = answers[i][3] & 15;
+ if (rcode != 0 && rcode != 3)
+ goto out;
+
+ /* Storing the length here commits the accepted answer.
+ * Immediately close TCP socket so as not to consume
+ * resources we no longer need. */
+ alens[i] = alen;
+ __syscall(SYS_close, pfd[i].fd);
+ pfd[i].fd = -1;
}
}
out:
pthread_cleanup_pop(1);
+ /* Disregard any incomplete TCP results */
+ for (i=0; i<nqueries; i++) if (alens[i]<0) alens[i] = 0;
+
return 0;
}
diff --git a/src/network/res_send.c b/src/network/res_send.c
index ee4abf1f..9593164d 100644
--- a/src/network/res_send.c
+++ b/src/network/res_send.c
@@ -1,8 +1,16 @@
#include <resolv.h>
+#include <string.h>
int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen)
{
- int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
+ int r;
+ if (anslen < 512) {
+ unsigned char buf[512];
+ r = __res_send(msg, msglen, buf, sizeof buf);
+ if (r >= 0) memcpy(answer, buf, r < anslen ? r : anslen);
+ return r;
+ }
+ r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
return r<0 || !anslen ? -1 : anslen;
}
diff --git a/src/process/_Fork.c b/src/process/_Fork.c
index da063868..fb0fdc2c 100644
--- a/src/process/_Fork.c
+++ b/src/process/_Fork.c
@@ -14,7 +14,6 @@ pid_t _Fork(void)
pid_t ret;
sigset_t set;
__block_all_sigs(&set);
- __aio_atfork(-1);
LOCK(__abort_lock);
#ifdef SYS_fork
ret = __syscall(SYS_fork);
@@ -32,7 +31,7 @@ pid_t _Fork(void)
if (libc.need_locks) libc.need_locks = -1;
}
UNLOCK(__abort_lock);
- __aio_atfork(!ret);
+ if (!ret) __aio_atfork(1);
__restore_sigs(&set);
return __syscall_ret(ret);
}
diff --git a/src/process/fork.c b/src/process/fork.c
index 54bc2892..56f19313 100644
--- a/src/process/fork.c
+++ b/src/process/fork.c
@@ -9,7 +9,6 @@ static volatile int *const dummy_lockptr = 0;
weak_alias(dummy_lockptr, __at_quick_exit_lockptr);
weak_alias(dummy_lockptr, __atexit_lockptr);
-weak_alias(dummy_lockptr, __dlerror_lockptr);
weak_alias(dummy_lockptr, __gettext_lockptr);
weak_alias(dummy_lockptr, __locale_lockptr);
weak_alias(dummy_lockptr, __random_lockptr);
@@ -24,7 +23,6 @@ weak_alias(dummy_lockptr, __vmlock_lockptr);
static volatile int *const *const atfork_locks[] = {
&__at_quick_exit_lockptr,
&__atexit_lockptr,
- &__dlerror_lockptr,
&__gettext_lockptr,
&__locale_lockptr,
&__random_lockptr,
@@ -38,6 +36,8 @@ static volatile int *const *const atfork_locks[] = {
static void dummy(int x) { }
weak_alias(dummy, __fork_handler);
weak_alias(dummy, __malloc_atfork);
+weak_alias(dummy, __aio_atfork);
+weak_alias(dummy, __pthread_key_atfork);
weak_alias(dummy, __ldso_atfork);
static void dummy_0(void) { }
@@ -52,6 +52,8 @@ pid_t fork(void)
int need_locks = libc.need_locks > 0;
if (need_locks) {
__ldso_atfork(-1);
+ __pthread_key_atfork(-1);
+ __aio_atfork(-1);
__inhibit_ptc();
for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
if (*atfork_locks[i]) LOCK(*atfork_locks[i]);
@@ -77,6 +79,8 @@ pid_t fork(void)
if (ret) UNLOCK(*atfork_locks[i]);
else **atfork_locks[i] = 0;
__release_ptc();
+ if (ret) __aio_atfork(0);
+ __pthread_key_atfork(!ret);
__ldso_atfork(!ret);
}
__restore_sigs(&set);
diff --git a/src/regex/glob.c b/src/regex/glob.c
index 9de080ed..a4906446 100644
--- a/src/regex/glob.c
+++ b/src/regex/glob.c
@@ -306,6 +306,3 @@ void globfree(glob_t *g)
g->gl_pathc = 0;
g->gl_pathv = NULL;
}
-
-weak_alias(glob, glob64);
-weak_alias(globfree, globfree64);
diff --git a/src/stat/__xstat.c b/src/stat/__xstat.c
index 630936a0..b4560df7 100644
--- a/src/stat/__xstat.c
+++ b/src/stat/__xstat.c
@@ -22,11 +22,6 @@ int __xstat(int ver, const char *path, struct stat *buf)
return stat(path, buf);
}
-weak_alias(__fxstat, __fxstat64);
-weak_alias(__fxstatat, __fxstatat64);
-weak_alias(__lxstat, __lxstat64);
-weak_alias(__xstat, __xstat64);
-
#endif
int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev)
diff --git a/src/stat/fstat.c b/src/stat/fstat.c
index 27db0ccb..fd28b8ac 100644
--- a/src/stat/fstat.c
+++ b/src/stat/fstat.c
@@ -11,7 +11,3 @@ int __fstat(int fd, struct stat *st)
}
weak_alias(__fstat, fstat);
-
-#if !_REDIR_TIME64
-weak_alias(fstat, fstat64);
-#endif
diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
index 74c51cf5..04506375 100644
--- a/src/stat/fstatat.c
+++ b/src/stat/fstatat.c
@@ -151,7 +151,3 @@ int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int f
}
weak_alias(__fstatat, fstatat);
-
-#if !_REDIR_TIME64
-weak_alias(fstatat, fstatat64);
-#endif
diff --git a/src/stat/lstat.c b/src/stat/lstat.c
index 6fe004de..6822fcae 100644
--- a/src/stat/lstat.c
+++ b/src/stat/lstat.c
@@ -5,7 +5,3 @@ int lstat(const char *restrict path, struct stat *restrict buf)
{
return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
}
-
-#if !_REDIR_TIME64
-weak_alias(lstat, lstat64);
-#endif
diff --git a/src/stat/stat.c b/src/stat/stat.c
index ea70efc4..23570e7a 100644
--- a/src/stat/stat.c
+++ b/src/stat/stat.c
@@ -5,7 +5,3 @@ int stat(const char *restrict path, struct stat *restrict buf)
{
return fstatat(AT_FDCWD, path, buf, 0);
}
-
-#if !_REDIR_TIME64
-weak_alias(stat, stat64);
-#endif
diff --git a/src/stat/statvfs.c b/src/stat/statvfs.c
index f65d1b54..bfbb5fee 100644
--- a/src/stat/statvfs.c
+++ b/src/stat/statvfs.c
@@ -56,8 +56,3 @@ int fstatvfs(int fd, struct statvfs *buf)
fixup(buf, &kbuf);
return 0;
}
-
-weak_alias(statvfs, statvfs64);
-weak_alias(statfs, statfs64);
-weak_alias(fstatvfs, fstatvfs64);
-weak_alias(fstatfs, fstatfs64);
diff --git a/src/stdio/fgetpos.c b/src/stdio/fgetpos.c
index 50813d2c..392f7323 100644
--- a/src/stdio/fgetpos.c
+++ b/src/stdio/fgetpos.c
@@ -7,5 +7,3 @@ int fgetpos(FILE *restrict f, fpos_t *restrict pos)
*(long long *)pos = off;
return 0;
}
-
-weak_alias(fgetpos, fgetpos64);
diff --git a/src/stdio/fgets.c b/src/stdio/fgets.c
index 6171f398..4a100b39 100644
--- a/src/stdio/fgets.c
+++ b/src/stdio/fgets.c
@@ -12,13 +12,14 @@ char *fgets(char *restrict s, int n, FILE *restrict f)
FLOCK(f);
- if (n--<=1) {
+ if (n<=1) {
f->mode |= f->mode-1;
FUNLOCK(f);
- if (n) return 0;
+ if (n<1) return 0;
*s = 0;
return s;
}
+ n--;
while (n) {
if (f->rpos != f->rend) {
diff --git a/src/stdio/fopen.c b/src/stdio/fopen.c
index e1b91e12..80bc341e 100644
--- a/src/stdio/fopen.c
+++ b/src/stdio/fopen.c
@@ -29,5 +29,3 @@ FILE *fopen(const char *restrict filename, const char *restrict mode)
__syscall(SYS_close, fd);
return 0;
}
-
-weak_alias(fopen, fopen64);
diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c
index 615d4b47..1641a4c5 100644
--- a/src/stdio/freopen.c
+++ b/src/stdio/freopen.c
@@ -40,6 +40,8 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re
fclose(f2);
}
+ f->mode = 0;
+ f->locale = 0;
FUNLOCK(f);
return f;
@@ -49,5 +51,3 @@ fail:
fclose(f);
return NULL;
}
-
-weak_alias(freopen, freopen64);
diff --git a/src/stdio/fseek.c b/src/stdio/fseek.c
index c07f7e95..c7425802 100644
--- a/src/stdio/fseek.c
+++ b/src/stdio/fseek.c
@@ -46,5 +46,3 @@ int fseek(FILE *f, long off, int whence)
}
weak_alias(__fseeko, fseeko);
-
-weak_alias(fseeko, fseeko64);
diff --git a/src/stdio/fsetpos.c b/src/stdio/fsetpos.c
index 77ab8d82..779cb3cc 100644
--- a/src/stdio/fsetpos.c
+++ b/src/stdio/fsetpos.c
@@ -4,5 +4,3 @@ int fsetpos(FILE *f, const fpos_t *pos)
{
return __fseeko(f, *(const long long *)pos, SEEK_SET);
}
-
-weak_alias(fsetpos, fsetpos64);
diff --git a/src/stdio/ftell.c b/src/stdio/ftell.c
index 1a2afbbc..1e1a08d8 100644
--- a/src/stdio/ftell.c
+++ b/src/stdio/ftell.c
@@ -37,5 +37,3 @@ long ftell(FILE *f)
}
weak_alias(__ftello, ftello);
-
-weak_alias(ftello, ftello64);
diff --git a/src/stdio/open_wmemstream.c b/src/stdio/open_wmemstream.c
index ed1b561d..b8ae4a79 100644
--- a/src/stdio/open_wmemstream.c
+++ b/src/stdio/open_wmemstream.c
@@ -40,8 +40,12 @@ fail:
static size_t wms_write(FILE *f, const unsigned char *buf, size_t len)
{
struct cookie *c = f->cookie;
- size_t len2;
+ size_t len2 = f->wpos - f->wbase;
wchar_t *newbuf;
+ if (len2) {
+ f->wpos = f->wbase;
+ if (wms_write(f, f->wbase, len2) < len2) return 0;
+ }
if (len + c->pos >= c->space) {
len2 = 2*c->space+1 | c->pos+len+1;
if (len2 > SSIZE_MAX/4) return 0;
diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c
index ae493987..2fa8803f 100644
--- a/src/stdio/tmpfile.c
+++ b/src/stdio/tmpfile.c
@@ -27,5 +27,3 @@ FILE *tmpfile(void)
}
return 0;
}
-
-weak_alias(tmpfile, tmpfile64);
diff --git a/src/temp/mkostemp.c b/src/temp/mkostemp.c
index d8dcb805..e3dfdd91 100644
--- a/src/temp/mkostemp.c
+++ b/src/temp/mkostemp.c
@@ -5,5 +5,3 @@ int mkostemp(char *template, int flags)
{
return __mkostemps(template, 0, flags);
}
-
-weak_alias(mkostemp, mkostemp64);
diff --git a/src/temp/mkostemps.c b/src/temp/mkostemps.c
index ef24eeae..093d2380 100644
--- a/src/temp/mkostemps.c
+++ b/src/temp/mkostemps.c
@@ -26,4 +26,3 @@ int __mkostemps(char *template, int len, int flags)
}
weak_alias(__mkostemps, mkostemps);
-weak_alias(__mkostemps, mkostemps64);
diff --git a/src/temp/mkstemp.c b/src/temp/mkstemp.c
index 166b8afe..76c835bb 100644
--- a/src/temp/mkstemp.c
+++ b/src/temp/mkstemp.c
@@ -4,5 +4,3 @@ int mkstemp(char *template)
{
return __mkostemps(template, 0, 0);
}
-
-weak_alias(mkstemp, mkstemp64);
diff --git a/src/temp/mkstemps.c b/src/temp/mkstemps.c
index 6b7531b5..f8eabfec 100644
--- a/src/temp/mkstemps.c
+++ b/src/temp/mkstemps.c
@@ -5,5 +5,3 @@ int mkstemps(char *template, int len)
{
return __mkostemps(template, len, 0);
}
-
-weak_alias(mkstemps, mkstemps64);
diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
index 2f9d5e97..2d3a98ea 100644
--- a/src/thread/pthread_cancel.c
+++ b/src/thread/pthread_cancel.c
@@ -77,7 +77,7 @@ void __testcancel()
static void init_cancellation()
{
struct sigaction sa = {
- .sa_flags = SA_SIGINFO | SA_RESTART,
+ .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK,
.sa_sigaction = cancel_handler
};
memset(&sa.sa_mask, -1, _NSIG/8);
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 6f187ee8..087f6206 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -107,6 +107,16 @@ _Noreturn void __pthread_exit(void *result)
/* At this point we are committed to thread termination. */
+ /* After the kernel thread exits, its tid may be reused. Clear it
+ * to prevent inadvertent use and inform functions that would use
+ * it that it's no longer available. At this point the killlock
+ * may be released, since functions that use it will consistently
+ * see the thread as having exited. Release it now so that no
+ * remaining locks (except thread list) are held if we end up
+ * resetting need_locks below. */
+ self->tid = 0;
+ UNLOCK(self->killlock);
+
/* Process robust list in userspace to handle non-pshared mutexes
* and the detached thread case where the robust list head will
* be invalid when the kernel would process it. */
@@ -159,12 +169,6 @@ _Noreturn void __pthread_exit(void *result)
a_store(&self->detach_state, DT_EXITED);
__wake(&self->detach_state, 1, 1);
- /* After the kernel thread exits, its tid may be reused. Clear it
- * to prevent inadvertent use and inform functions that would use
- * it that it's no longer available. */
- self->tid = 0;
- UNLOCK(self->killlock);
-
for (;;) __syscall(SYS_exit, 0);
}
diff --git a/src/thread/pthread_key_create.c b/src/thread/pthread_key_create.c
index d1120941..39770c7a 100644
--- a/src/thread/pthread_key_create.c
+++ b/src/thread/pthread_key_create.c
@@ -1,4 +1,5 @@
#include "pthread_impl.h"
+#include "fork_impl.h"
volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX;
void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 };
@@ -20,6 +21,13 @@ static void dummy_0(void)
weak_alias(dummy_0, __tl_lock);
weak_alias(dummy_0, __tl_unlock);
+void __pthread_key_atfork(int who)
+{
+ if (who<0) __pthread_rwlock_rdlock(&key_lock);
+ else if (!who) __pthread_rwlock_unlock(&key_lock);
+ else key_lock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER;
+}
+
int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
{
pthread_t self = __pthread_self();
diff --git a/src/thread/synccall.c b/src/thread/synccall.c
index d58c851f..a6b177c0 100644
--- a/src/thread/synccall.c
+++ b/src/thread/synccall.c
@@ -45,7 +45,7 @@ void __synccall(void (*func)(void *), void *ctx)
{
sigset_t oldmask;
int cs, i, r;
- struct sigaction sa = { .sa_flags = SA_RESTART, .sa_handler = handler };
+ struct sigaction sa = { .sa_flags = SA_RESTART | SA_ONSTACK, .sa_handler = handler };
pthread_t self = __pthread_self(), td;
int count = 0;
diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c
index c7e66a51..4d2ec22f 100644
--- a/src/time/clock_gettime.c
+++ b/src/time/clock_gettime.c
@@ -42,6 +42,9 @@ static int cgt_init(clockid_t clk, struct timespec *ts)
p = cgt_time32_wrap;
}
}
+#ifdef VDSO_CGT_WORKAROUND
+ if (!__vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM)) p = 0;
+#endif
#endif
int (*f)(clockid_t, struct timespec *) =
(int (*)(clockid_t, struct timespec *))p;
diff --git a/src/time/timer_create.c b/src/time/timer_create.c
index 4bef2390..cd32c945 100644
--- a/src/time/timer_create.c
+++ b/src/time/timer_create.c
@@ -43,6 +43,8 @@ static void *start(void *arg)
union sigval val = args->sev->sigev_value;
pthread_barrier_wait(&args->b);
+ if (self->cancel)
+ return 0;
for (;;) {
siginfo_t si;
while (sigwaitinfo(SIGTIMER_SET, &si) < 0);
@@ -113,8 +115,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
ksev.sigev_signo = SIGTIMER;
ksev.sigev_notify = SIGEV_THREAD_ID;
ksev.sigev_tid = td->tid;
- if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
+ if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) {
timerid = -1;
+ td->cancel = 1;
+ }
td->timer_id = timerid;
pthread_barrier_wait(&args.b);
if (timerid < 0) return -1;
diff --git a/src/unistd/ftruncate.c b/src/unistd/ftruncate.c
index b41be0fa..54ff34bc 100644
--- a/src/unistd/ftruncate.c
+++ b/src/unistd/ftruncate.c
@@ -5,5 +5,3 @@ int ftruncate(int fd, off_t length)
{
return syscall(SYS_ftruncate, fd, __SYSCALL_LL_O(length));
}
-
-weak_alias(ftruncate, ftruncate64);
diff --git a/src/unistd/lseek.c b/src/unistd/lseek.c
index b4984f3e..f5b66682 100644
--- a/src/unistd/lseek.c
+++ b/src/unistd/lseek.c
@@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence)
}
weak_alias(__lseek, lseek);
-weak_alias(__lseek, lseek64);
diff --git a/src/unistd/mipsn32/lseek.c b/src/unistd/mipsn32/lseek.c
index 60e74a51..0f6cbcaa 100644
--- a/src/unistd/mipsn32/lseek.c
+++ b/src/unistd/mipsn32/lseek.c
@@ -17,4 +17,3 @@ off_t __lseek(int fd, off_t offset, int whence)
}
weak_alias(__lseek, lseek);
-weak_alias(__lseek, lseek64);
diff --git a/src/unistd/pread.c b/src/unistd/pread.c
index 5681b045..b03fb0ad 100644
--- a/src/unistd/pread.c
+++ b/src/unistd/pread.c
@@ -5,5 +5,3 @@ ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
{
return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_PRW(ofs));
}
-
-weak_alias(pread, pread64);
diff --git a/src/unistd/preadv.c b/src/unistd/preadv.c
index 8376d60f..890ab403 100644
--- a/src/unistd/preadv.c
+++ b/src/unistd/preadv.c
@@ -8,5 +8,3 @@ ssize_t preadv(int fd, const struct iovec *iov, int count, off_t ofs)
return syscall_cp(SYS_preadv, fd, iov, count,
(long)(ofs), (long)(ofs>>32));
}
-
-weak_alias(preadv, preadv64);
diff --git a/src/unistd/pwrite.c b/src/unistd/pwrite.c
index ca376576..869b69f0 100644
--- a/src/unistd/pwrite.c
+++ b/src/unistd/pwrite.c
@@ -5,5 +5,3 @@ ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
{
return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_PRW(ofs));
}
-
-weak_alias(pwrite, pwrite64);
diff --git a/src/unistd/pwritev.c b/src/unistd/pwritev.c
index f5a612c4..becf9deb 100644
--- a/src/unistd/pwritev.c
+++ b/src/unistd/pwritev.c
@@ -8,5 +8,3 @@ ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs)
return syscall_cp(SYS_pwritev, fd, iov, count,
(long)(ofs), (long)(ofs>>32));
}
-
-weak_alias(pwritev, pwritev64);
diff --git a/src/unistd/truncate.c b/src/unistd/truncate.c
index 97296800..077351e1 100644
--- a/src/unistd/truncate.c
+++ b/src/unistd/truncate.c
@@ -5,5 +5,3 @@ int truncate(const char *path, off_t length)
{
return syscall(SYS_truncate, path, __SYSCALL_LL_O(length));
}
-
-weak_alias(truncate, truncate64);
diff --git a/src/unistd/x32/lseek.c b/src/unistd/x32/lseek.c
index 32636429..5f93292f 100644
--- a/src/unistd/x32/lseek.c
+++ b/src/unistd/x32/lseek.c
@@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence)
}
weak_alias(__lseek, lseek);
-weak_alias(__lseek, lseek64);