diff options
208 files changed, 1130 insertions, 517 deletions
@@ -1 +1 @@ -1.2.2 +1.2.3 @@ -2287,3 +2287,43 @@ arch-specific bugs fixed: - i386 __set_thread_area fallback for pre-2.6 kernels didn't work - missing O_LARGEFILE macro value on x86_64, x32, mips64 - unpredictable s390x breakage from failure to preserve call-saved registers + + + +1.2.3 release notes + +new features: +- qsort_r function (POSIX-future) +- pthread_getname_np extension function +- hard float on SPE FPU for powerpc-sf +- SEEK_DATA and SEEK_HOLE exposed in unistd.h (Linux extensions) + +compatibility: +- free now preserves errno (POSIX-future requirement) +- setjmp is declared explicitly with returns_twice for non-GCC compilers +- macro version of isascii is no longer defined for C++ +- dynamic linker now tolerates zero-length LOAD segments +- epoll_[p]wait is now a cancellation point +- pwd/grp functions no longer fail on systems without AF_UNIX support +- POSIX TZ parsing is stricter to allow more names to fallback to files +- NULL is now defined as nullptr when used in C++11 or later +- gettext now accepts null pointer as argument + +bugs fixed: +- old regression in wcwidth of Hangul combining (vowel/final) letters +- duplocale used wrong malloc when malloc was replaced (1.2.2 regression) +- fmaf rounded wrong on archs without FE_TOWARDZERO (all softfloat archs) +- popen didn't honor requirement not to leak other popen pipe fds to child +- aligned_alloc and variants crashed on allocation failure +- dl_iterate_phdr reported incorrect module TLS pointers +- mishandling of some inputs in acoshf and expm1f and functions using them +- potentially wrong-sign zero in cproj functions at infinity +- multiple bugs in legacy function cuserid +- minor posix_spawn file actions API conformance issues +- pthread_setname_np fd leak +- out-of-bound read in zoneinfo handling with distant-past times +- out-of-tree builds lacked generated debug cfi for x86 asm + +arch-specific bugs fixed: +- powerpc (32-bit) struct shmid_ds layout was wrong for some fields +- time64 struct layout was wrong in sound ioctl fallback (32-bit archs) diff --git a/arch/aarch64/bits/syscall.h.in b/arch/aarch64/bits/syscall.h.in index 1ad467c0..5f420e61 100644 --- a/arch/aarch64/bits/syscall.h.in +++ b/arch/aarch64/bits/syscall.h.in @@ -294,4 +294,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/arm/bits/syscall.h.in b/arch/arm/bits/syscall.h.in index cf9e3411..048fdea7 100644 --- a/arch/arm/bits/syscall.h.in +++ b/arch/arm/bits/syscall.h.in @@ -394,6 +394,11 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 #define __ARM_NR_breakpoint 0x0f0001 #define __ARM_NR_cacheflush 0x0f0002 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/arch/i386/bits/syscall.h.in b/arch/i386/bits/syscall.h.in index 5d1c4d7a..46ffe1d9 100644 --- a/arch/i386/bits/syscall.h.in +++ b/arch/i386/bits/syscall.h.in @@ -431,4 +431,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/m68k/bits/syscall.h.in b/arch/m68k/bits/syscall.h.in index 6794b1a0..a0c63323 100644 --- a/arch/m68k/bits/syscall.h.in +++ b/arch/m68k/bits/syscall.h.in @@ -411,3 +411,8 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/microblaze/bits/signal.h b/arch/microblaze/bits/signal.h index 490f83bf..f25b7c6a 100644 --- a/arch/microblaze/bits/signal.h +++ b/arch/microblaze/bits/signal.h @@ -46,7 +46,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #endif diff --git a/arch/microblaze/bits/syscall.h.in b/arch/microblaze/bits/syscall.h.in index 7f71df3b..931d7919 100644 --- a/arch/microblaze/bits/syscall.h.in +++ b/arch/microblaze/bits/syscall.h.in @@ -432,4 +432,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/mips/bits/signal.h b/arch/mips/bits/signal.h index 1b69e762..a3b3857a 100644 --- a/arch/mips/bits/signal.h +++ b/arch/mips/bits/signal.h @@ -66,7 +66,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #undef SIG_BLOCK #undef SIG_UNBLOCK diff --git a/arch/mips/bits/syscall.h.in b/arch/mips/bits/syscall.h.in index d54845b2..63e3503a 100644 --- a/arch/mips/bits/syscall.h.in +++ b/arch/mips/bits/syscall.h.in @@ -413,4 +413,9 @@ #define __NR_pidfd_getfd 4438 #define __NR_faccessat2 4439 #define __NR_process_madvise 4440 +#define __NR_epoll_pwait2 4441 +#define __NR_mount_setattr 4442 +#define __NR_landlock_create_ruleset 4444 +#define __NR_landlock_add_rule 4445 +#define __NR_landlock_restrict_self 4446 diff --git a/arch/mips/ksigaction.h b/arch/mips/ksigaction.h index 63fdfab0..485abf75 100644 --- a/arch/mips/ksigaction.h +++ b/arch/mips/ksigaction.h @@ -4,10 +4,7 @@ struct k_sigaction { unsigned flags; void (*handler)(int); unsigned long mask[4]; - /* The following field is past the end of the structure the - * kernel will read or write, and exists only to avoid having - * mips-specific preprocessor conditionals in sigaction.c. */ - void (*restorer)(); + void *unused; }; hidden void __restore(), __restore_rt(); diff --git a/arch/mips/reloc.h b/arch/mips/reloc.h index 88d23639..f4023b16 100644 --- a/arch/mips/reloc.h +++ b/arch/mips/reloc.h @@ -29,6 +29,7 @@ #define NEED_MIPS_GOT_RELOCS 1 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP +#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT)) #define CRTJMP(pc,sp) __asm__ __volatile__( \ diff --git a/arch/mips64/bits/signal.h b/arch/mips64/bits/signal.h index 4f91c9fc..ffec7fd0 100644 --- a/arch/mips64/bits/signal.h +++ b/arch/mips64/bits/signal.h @@ -85,7 +85,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #undef SIG_BLOCK #undef SIG_UNBLOCK diff --git a/arch/mips64/bits/syscall.h.in b/arch/mips64/bits/syscall.h.in index 920b4358..b89965d1 100644 --- a/arch/mips64/bits/syscall.h.in +++ b/arch/mips64/bits/syscall.h.in @@ -343,4 +343,9 @@ #define __NR_pidfd_getfd 5438 #define __NR_faccessat2 5439 #define __NR_process_madvise 5440 +#define __NR_epoll_pwait2 5441 +#define __NR_mount_setattr 5442 +#define __NR_landlock_create_ruleset 5444 +#define __NR_landlock_add_rule 5445 +#define __NR_landlock_restrict_self 5446 diff --git a/arch/mips64/ksigaction.h b/arch/mips64/ksigaction.h index c16e4731..b4d0fa5f 100644 --- a/arch/mips64/ksigaction.h +++ b/arch/mips64/ksigaction.h @@ -4,7 +4,7 @@ struct k_sigaction { unsigned flags; void (*handler)(int); unsigned long mask[2]; - void (*restorer)(); + void *unused; }; hidden void __restore(), __restore_rt(); diff --git a/arch/mips64/reloc.h b/arch/mips64/reloc.h index fdb5edc9..145d8b0b 100644 --- a/arch/mips64/reloc.h +++ b/arch/mips64/reloc.h @@ -38,6 +38,7 @@ #define NEED_MIPS_GOT_RELOCS 1 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP +#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT)) #define CRTJMP(pc,sp) __asm__ __volatile__( \ diff --git a/arch/mipsn32/bits/signal.h b/arch/mipsn32/bits/signal.h index 4f91c9fc..ffec7fd0 100644 --- a/arch/mipsn32/bits/signal.h +++ b/arch/mipsn32/bits/signal.h @@ -85,7 +85,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #undef SIG_BLOCK #undef SIG_UNBLOCK diff --git a/arch/mipsn32/bits/syscall.h.in b/arch/mipsn32/bits/syscall.h.in index e6dad688..bb2d04a8 100644 --- a/arch/mipsn32/bits/syscall.h.in +++ b/arch/mipsn32/bits/syscall.h.in @@ -367,4 +367,9 @@ #define __NR_pidfd_getfd 6438 #define __NR_faccessat2 6439 #define __NR_process_madvise 6440 +#define __NR_epoll_pwait2 6441 +#define __NR_mount_setattr 6442 +#define __NR_landlock_create_ruleset 6444 +#define __NR_landlock_add_rule 6445 +#define __NR_landlock_restrict_self 6446 diff --git a/arch/mipsn32/ksigaction.h b/arch/mipsn32/ksigaction.h index b565f1fc..485abf75 100644 --- a/arch/mipsn32/ksigaction.h +++ b/arch/mipsn32/ksigaction.h @@ -4,7 +4,7 @@ struct k_sigaction { unsigned flags; void (*handler)(int); unsigned long mask[4]; - void (*restorer)(); + void *unused; }; hidden void __restore(), __restore_rt(); diff --git a/arch/mipsn32/reloc.h b/arch/mipsn32/reloc.h index 47c6e591..bf00bd6a 100644 --- a/arch/mipsn32/reloc.h +++ b/arch/mipsn32/reloc.h @@ -29,6 +29,7 @@ #define NEED_MIPS_GOT_RELOCS 1 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP +#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT)) #define CRTJMP(pc,sp) __asm__ __volatile__( \ diff --git a/arch/or1k/bits/signal.h b/arch/or1k/bits/signal.h index be576d1d..c45be676 100644 --- a/arch/or1k/bits/signal.h +++ b/arch/or1k/bits/signal.h @@ -43,7 +43,6 @@ typedef struct __ucontext { #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #endif diff --git a/arch/or1k/bits/syscall.h.in b/arch/or1k/bits/syscall.h.in index 463ee901..2b5f2052 100644 --- a/arch/or1k/bits/syscall.h.in +++ b/arch/or1k/bits/syscall.h.in @@ -316,4 +316,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/powerpc/bits/syscall.h.in b/arch/powerpc/bits/syscall.h.in index db4d0ca4..b1605a58 100644 --- a/arch/powerpc/bits/syscall.h.in +++ b/arch/powerpc/bits/syscall.h.in @@ -420,4 +420,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/powerpc64/bits/syscall.h.in b/arch/powerpc64/bits/syscall.h.in index a128890b..b3a8fba0 100644 --- a/arch/powerpc64/bits/syscall.h.in +++ b/arch/powerpc64/bits/syscall.h.in @@ -392,4 +392,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h index 287367db..fd6157a3 100644 --- a/arch/riscv64/bits/signal.h +++ b/arch/riscv64/bits/signal.h @@ -76,7 +76,6 @@ typedef struct __ucontext #define SA_RESTART 0x10000000 #define SA_NODEFER 0x40000000 #define SA_RESETHAND 0x80000000 -#define SA_RESTORER 0x04000000 #endif diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in index 39c0d650..b534afe8 100644 --- a/arch/riscv64/bits/syscall.h.in +++ b/arch/riscv64/bits/syscall.h.in @@ -294,6 +294,11 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 #define __NR_sysriscv __NR_arch_specific_syscall #define __NR_riscv_flush_icache (__NR_sysriscv + 15) diff --git a/arch/s390x/bits/ptrace.h b/arch/s390x/bits/ptrace.h index d50e3262..a06cb077 100644 --- a/arch/s390x/bits/ptrace.h +++ b/arch/s390x/bits/ptrace.h @@ -1,4 +1,7 @@ #define PTRACE_SINGLEBLOCK 12 +#define PTRACE_OLDSETOPTIONS 21 +#define PTRACE_SYSEMU 31 +#define PTRACE_SYSEMU_SINGLESTEP 32 #define PTRACE_PEEKUSR_AREA 0x5000 #define PTRACE_POKEUSR_AREA 0x5001 #define PTRACE_GET_LAST_BREAK 0x5006 diff --git a/arch/s390x/bits/syscall.h.in b/arch/s390x/bits/syscall.h.in index 9c8d984e..dfc38479 100644 --- a/arch/s390x/bits/syscall.h.in +++ b/arch/s390x/bits/syscall.h.in @@ -357,4 +357,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/sh/bits/syscall.h.in b/arch/sh/bits/syscall.h.in index 17dd7e07..ff14f54d 100644 --- a/arch/sh/bits/syscall.h.in +++ b/arch/sh/bits/syscall.h.in @@ -404,4 +404,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 diff --git a/arch/x32/bits/syscall.h.in b/arch/x32/bits/syscall.h.in index 5361442e..5d22fa17 100644 --- a/arch/x32/bits/syscall.h.in +++ b/arch/x32/bits/syscall.h.in @@ -303,6 +303,11 @@ #define __NR_pidfd_getfd (0x40000000 + 438) #define __NR_faccessat2 (0x40000000 + 439) #define __NR_process_madvise (0x40000000 + 440) +#define __NR_epoll_pwait2 (0x40000000 + 441) +#define __NR_mount_setattr (0x40000000 + 442) +#define __NR_landlock_create_ruleset (0x40000000 + 444) +#define __NR_landlock_add_rule (0x40000000 + 445) +#define __NR_landlock_restrict_self (0x40000000 + 446) #define __NR_rt_sigaction (0x40000000 + 512) diff --git a/arch/x32/bits/user.h b/arch/x32/bits/user.h index 4073cc06..eac82a14 100644 --- a/arch/x32/bits/user.h +++ b/arch/x32/bits/user.h @@ -1,5 +1,5 @@ #undef __WORDSIZE -#define __WORDSIZE 64 +#define __WORDSIZE 32 typedef struct user_fpregs_struct { uint16_t cwd, swd, ftw, fop; diff --git a/arch/x86_64/bits/syscall.h.in b/arch/x86_64/bits/syscall.h.in index e943883d..c3882de7 100644 --- a/arch/x86_64/bits/syscall.h.in +++ b/arch/x86_64/bits/syscall.h.in @@ -350,4 +350,9 @@ #define __NR_pidfd_getfd 438 #define __NR_faccessat2 439 #define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 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); @@ -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. @@ -409,7 +417,7 @@ test "$debug" = yes && CFLAGS_AUTO=-g # printf "checking whether we should preprocess assembly to add debugging information... " if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" && - test -f "tools/add-cfi.$ARCH.awk" && + test -f "$srcdir/tools/add-cfi.$ARCH.awk" && printf ".file 1 \"srcfile.s\"\n.line 1\n.cfi_startproc\n.cfi_endproc" | $CC -g -x assembler -c -o /dev/null 2>/dev/null - then ADD_CFI=yes @@ -723,11 +731,6 @@ fi test "$SUBARCH" \ && printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH" -case "$ARCH$SUBARCH" in -arm) ASMSUBARCH=el ;; -*) ASMSUBARCH=$SUBARCH ;; -esac - # # Some archs (powerpc) have different possible long double formats # that the compiler can be configured for. The logic for whether this 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/elf.h b/include/elf.h index 5170f3e2..23f2c4bc 100644 --- a/include/elf.h +++ b/include/elf.h @@ -385,7 +385,8 @@ typedef struct { #define SHT_PREINIT_ARRAY 16 #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 -#define SHT_NUM 19 +#define SHT_RELR 19 +#define SHT_NUM 20 #define SHT_LOOS 0x60000000 #define SHT_GNU_ATTRIBUTES 0x6ffffff5 #define SHT_GNU_HASH 0x6ffffff6 @@ -436,6 +437,7 @@ typedef struct { } Elf64_Chdr; #define ELFCOMPRESS_ZLIB 1 +#define ELFCOMPRESS_ZSTD 2 #define ELFCOMPRESS_LOOS 0x60000000 #define ELFCOMPRESS_HIOS 0x6fffffff #define ELFCOMPRESS_LOPROC 0x70000000 @@ -687,6 +689,7 @@ typedef struct { #define NT_ARM_PACA_KEYS 0x407 #define NT_ARM_PACG_KEYS 0x408 #define NT_ARM_TAGGED_ADDR_CTRL 0x409 +#define NT_ARM_PAC_ENABLED_KEYS 0x40a #define NT_METAG_CBUF 0x500 #define NT_METAG_RPIPE 0x501 #define NT_METAG_TLS 0x502 @@ -753,7 +756,10 @@ typedef struct { #define DT_PREINIT_ARRAY 32 #define DT_PREINIT_ARRAYSZ 33 #define DT_SYMTAB_SHNDX 34 -#define DT_NUM 35 +#define DT_RELRSZ 35 +#define DT_RELR 36 +#define DT_RELRENT 37 +#define DT_NUM 38 #define DT_LOOS 0x6000000d #define DT_HIOS 0x6ffff000 #define DT_LOPROC 0x70000000 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/locale.h b/include/locale.h index ce384381..11106fea 100644 --- a/include/locale.h +++ b/include/locale.h @@ -7,7 +7,9 @@ extern "C" { #include <features.h> -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) 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/netinet/if_ether.h b/include/netinet/if_ether.h index 55a2ff1b..3479f511 100644 --- a/include/netinet/if_ether.h +++ b/include/netinet/if_ether.h @@ -66,6 +66,7 @@ #define ETH_P_1588 0x88F7 #define ETH_P_NCSI 0x88F8 #define ETH_P_PRP 0x88FB +#define ETH_P_CFM 0x8902 #define ETH_P_FCOE 0x8906 #define ETH_P_TDLS 0x890D #define ETH_P_FIP 0x8914 diff --git a/include/netinet/in.h b/include/netinet/in.h index f9594339..fb628b61 100644 --- a/include/netinet/in.h +++ b/include/netinet/in.h @@ -48,6 +48,7 @@ struct ipv6_mreq { #define INADDR_BROADCAST ((in_addr_t) 0xffffffff) #define INADDR_NONE ((in_addr_t) 0xffffffff) #define INADDR_LOOPBACK ((in_addr_t) 0x7f000001) +#define INADDR_DUMMY ((in_addr_t) 0xc0000008) #define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) #define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) diff --git a/include/netinet/tcp.h b/include/netinet/tcp.h index b7b997f5..fad1d844 100644 --- a/include/netinet/tcp.h +++ b/include/netinet/tcp.h @@ -80,6 +80,8 @@ enum { TCP_NLA_SRTT, TCP_NLA_TIMEOUT_REHASH, TCP_NLA_BYTES_NOTSENT, + TCP_NLA_EDT, + TCP_NLA_TTL, }; #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) @@ -281,12 +283,21 @@ struct tcp_repair_window { uint32_t rcv_wup; }; +#define TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT 0x1 + struct tcp_zerocopy_receive { uint64_t address; uint32_t length; uint32_t recv_skip_hint; uint32_t inq; int32_t err; + uint64_t copybuf_address; + int32_t copybuf_len; + uint32_t flags; + uint64_t msg_control; + uint64_t msg_controllen; + uint32_t msg_flags; + uint32_t reserved; }; #endif diff --git a/include/signal.h b/include/signal.h index f270a594..c347f861 100644 --- a/include/signal.h +++ b/include/signal.h @@ -178,6 +178,9 @@ struct sigaction { #define sa_handler __sa_handler.sa_handler #define sa_sigaction __sa_handler.sa_sigaction +#define SA_UNSUPPORTED 0x00000400 +#define SA_EXPOSE_TAGBITS 0x00000800 + struct sigevent { union sigval sigev_value; int sigev_signo; @@ -261,6 +264,9 @@ void (*sigset(int, void (*)(int)))(int); #if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) #define NSIG _NSIG typedef void (*sig_t)(int); + +#define SYS_SECCOMP 1 +#define SYS_USER_DISPATCH 2 #endif #ifdef _GNU_SOURCE diff --git a/include/stddef.h b/include/stddef.h index bd753853..f25b8639 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -1,7 +1,9 @@ #ifndef _STDDEF_H #define _STDDEF_H -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/stdio.h b/include/stdio.h index 3604198c..cb858618 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -25,7 +25,9 @@ extern "C" { #include <bits/alltypes.h> -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) @@ -203,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 b54a051f..475190bf 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -7,7 +7,9 @@ extern "C" { #include <features.h> -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) @@ -93,7 +95,7 @@ size_t __ctype_get_mb_cur_max(void); #define WTERMSIG(s) ((s) & 0x7f) #define WSTOPSIG(s) WEXITSTATUS(s) #define WIFEXITED(s) (!WTERMSIG(s)) -#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00) +#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001U)>>8) > 0x7f00) #define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu) int posix_memalign (void **, size_t, size_t); @@ -146,6 +148,7 @@ int clearenv(void); #define WCOREDUMP(s) ((s) & 0x80) #define WIFCONTINUED(s) ((s) == 0xffff) void *reallocarray (void *, size_t, size_t); +void qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *); #endif #ifdef _GNU_SOURCE @@ -160,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/string.h b/include/string.h index 795a2abc..db73d2a9 100644 --- a/include/string.h +++ b/include/string.h @@ -7,7 +7,9 @@ extern "C" { #include <features.h> -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) @@ -71,6 +73,7 @@ char *strsignal(int); char *strerror_l (int, locale_t); int strcoll_l (const char *, const char *, locale_t); size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t); +void *memmem(const void *, size_t, const void *, size_t); #endif #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ @@ -90,7 +93,6 @@ void explicit_bzero (void *, size_t); int strverscmp (const char *, const char *); char *strchrnul(const char *, int); char *strcasestr(const char *, const char *); -void *memmem(const void *, size_t, const void *, size_t); void *memrchr(const void *, int, size_t); void *mempcpy(void *, const void *, size_t); #ifndef __cplusplus diff --git a/include/strings.h b/include/strings.h index db0960b4..b7a5ea08 100644 --- a/include/strings.h +++ b/include/strings.h @@ -5,6 +5,7 @@ extern "C" { #endif +#include <features.h> #define __NEED_size_t #define __NEED_locale_t 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/prctl.h b/include/sys/prctl.h index 4ba73f42..087a75c9 100644 --- a/include/sys/prctl.h +++ b/include/sys/prctl.h @@ -168,6 +168,15 @@ struct prctl_mm_map { #define PR_SET_IO_FLUSHER 57 #define PR_GET_IO_FLUSHER 58 +#define PR_SET_SYSCALL_USER_DISPATCH 59 +#define PR_SYS_DISPATCH_OFF 0 +#define PR_SYS_DISPATCH_ON 1 +#define SYSCALL_DISPATCH_FILTER_ALLOW 0 +#define SYSCALL_DISPATCH_FILTER_BLOCK 1 + +#define PR_PAC_SET_ENABLED_KEYS 60 +#define PR_PAC_GET_ENABLED_KEYS 61 + int prctl (int, ...); #ifdef __cplusplus diff --git a/include/sys/ptrace.h b/include/sys/ptrace.h index 5d62a985..c72e3c06 100644 --- a/include/sys/ptrace.h +++ b/include/sys/ptrace.h @@ -42,6 +42,7 @@ extern "C" { #define PTRACE_SECCOMP_GET_FILTER 0x420c #define PTRACE_SECCOMP_GET_METADATA 0x420d #define PTRACE_GET_SYSCALL_INFO 0x420e +#define PTRACE_GET_RSEQ_CONFIGURATION 0x420f #define PT_READ_I PTRACE_PEEKTEXT #define PT_READ_D PTRACE_PEEKDATA @@ -130,6 +131,14 @@ struct __ptrace_syscall_info { }; }; +struct __ptrace_rseq_configuration { + uint64_t rseq_abi_pointer; + uint32_t rseq_abi_size; + uint32_t signature; + uint32_t flags; + uint32_t pad; +}; + long ptrace(int, ...); #ifdef __cplusplus 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/socket.h b/include/sys/socket.h index 38f5bb17..6dc1e40a 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -289,6 +289,8 @@ struct linger { #define SCM_TXTIME SO_TXTIME #define SO_BINDTOIFINDEX 62 #define SO_DETACH_REUSEPORT_BPF 68 +#define SO_PREFER_BUSY_POLL 69 +#define SO_BUSY_POLL_BUDGET 70 #ifndef SOL_SOCKET #define SOL_SOCKET 1 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/sys/wait.h b/include/sys/wait.h index d4b1f2e1..8ced671b 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -50,7 +50,7 @@ pid_t wait4 (pid_t, int *, int, struct rusage *); #define WSTOPSIG(s) WEXITSTATUS(s) #define WCOREDUMP(s) ((s) & 0x80) #define WIFEXITED(s) (!WTERMSIG(s)) -#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00) +#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001U)>>8) > 0x7f00) #define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu) #define WIFCONTINUED(s) ((s) == 0xffff) diff --git a/include/time.h b/include/time.h index 5494df18..3d948372 100644 --- a/include/time.h +++ b/include/time.h @@ -7,7 +7,9 @@ extern "C" { #include <features.h> -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) diff --git a/include/unistd.h b/include/unistd.h index 13064026..5bc7f798 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -14,8 +14,12 @@ extern "C" { #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 +#define SEEK_DATA 3 +#define SEEK_HOLE 4 -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) @@ -194,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 @@ -421,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 @@ -463,6 +469,8 @@ pid_t gettid(void); #define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS 1147 #define _CS_V6_ENV 1148 #define _CS_V7_ENV 1149 +#define _CS_POSIX_V7_THREADS_CFLAGS 1150 +#define _CS_POSIX_V7_THREADS_LDFLAGS 1151 #ifdef __cplusplus } diff --git a/include/wchar.h b/include/wchar.h index 88eb55b1..ed5d774d 100644 --- a/include/wchar.h +++ b/include/wchar.h @@ -38,7 +38,9 @@ extern "C" { #define WCHAR_MIN (-1-0x7fffffff+L'\0') #endif -#ifdef __cplusplus +#if __cplusplus >= 201103L +#define NULL nullptr +#elif defined(__cplusplus) #define NULL 0L #else #define NULL ((void*)0) 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 5b9c8be4..fde5f346 100644 --- a/ldso/dynlink.c +++ b/ldso/dynlink.c @@ -21,15 +21,23 @@ #include <sys/membarrier.h> #include "pthread_impl.h" #include "fork_impl.h" -#include "libc.h" #include "dynlink.h" +static size_t ldso_page_size; +#ifndef PAGE_SIZE +#define PAGE_SIZE ldso_page_size +#endif + +#include "libc.h" + #define malloc __libc_malloc #define calloc __libc_calloc #define realloc __libc_realloc #define free __libc_free -static void error(const char *, ...); +static void error_impl(const char *, ...); +static void error_noop(const char *, ...); +static void (*error)(const char *, ...) = error_noop; #define MAXP2(a,b) (-(-(a)&-(b))) #define ALIGN(x,y) ((x)+(y)-1 & -(y)) @@ -208,7 +216,8 @@ static void decode_vec(size_t *v, size_t *a, size_t cnt) size_t i; for (i=0; i<cnt; i++) a[i] = 0; for (; v[0]; v+=2) if (v[0]-1<cnt-1) { - a[0] |= 1UL<<v[0]; + if (v[0] < 8*sizeof(long)) + a[0] |= 1UL<<v[0]; a[v[0]] = v[1]; } } @@ -334,6 +343,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; @@ -387,6 +429,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)) { @@ -513,6 +556,24 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri } } +static void do_relr_relocs(struct dso *dso, size_t *relr, size_t relr_size) +{ + if (dso == &ldso) return; /* self-relocation was done in _dlstart */ + unsigned char *base = dso->base; + size_t *reloc_addr; + for (; relr_size; relr++, relr_size-=sizeof(size_t)) + if ((relr[0]&1) == 0) { + reloc_addr = laddr(dso, relr[0]); + *reloc_addr++ += (size_t)base; + } else { + int i = 0; + for (size_t bitmap=relr[0]; (bitmap>>=1); i++) + if (bitmap&1) + reloc_addr[i] += (size_t)base; + reloc_addr += 8*sizeof(size_t)-1; + } +} + static void redo_lazy_relocs() { struct dso *p = lazy_head, *next; @@ -866,7 +927,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; } @@ -1355,13 +1416,17 @@ static void reloc_all(struct dso *p) 2+(dyn[DT_PLTREL]==DT_RELA)); do_relocs(p, laddr(p, dyn[DT_REL]), dyn[DT_RELSZ], 2); do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3); - - if (head != &ldso && p->relro_start != p->relro_end && - mprotect(laddr(p, p->relro_start), p->relro_end-p->relro_start, PROT_READ) - && errno != ENOSYS) { - error("Error relocating %s: RELRO protection failed: %m", - p->name); - if (runtime) longjmp(*rtld_fail, 1); + if (!DL_FDPIC) + do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]); + + if (head != &ldso && p->relro_start != p->relro_end) { + long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start), + p->relro_end-p->relro_start, PROT_READ); + if (ret != 0 && ret != -ENOSYS) { + error("Error relocating %s: RELRO protection failed: %m", + p->name); + if (runtime) longjmp(*rtld_fail, 1); + } } p->relocated = 1; @@ -1664,6 +1729,7 @@ hidden void __dls2(unsigned char *base, size_t *sp) ldso.phnum = ehdr->e_phnum; ldso.phdr = laddr(&ldso, ehdr->e_phoff); ldso.phentsize = ehdr->e_phentsize; + search_vec(auxv, &ldso_page_size, AT_PAGESZ); kernel_mapped_dso(&ldso); decode_dyn(&ldso); @@ -1756,6 +1822,9 @@ void __dls3(size_t *sp, size_t *auxv) env_preload = getenv("LD_PRELOAD"); } + /* Activate error handler function */ + error = error_impl; + /* If the main program was already loaded by the kernel, * AT_PHDR will point to some location other than the dynamic * linker's program headers. */ @@ -1923,6 +1992,10 @@ void __dls3(size_t *sp, size_t *auxv) size_t *ptr = (size_t *) app.dynv[i+1]; *ptr = (size_t)&debug; } + if (app.dynv[i]==DT_DEBUG_INDIRECT_REL) { + size_t *ptr = (size_t *)((size_t)&app.dynv[i] + app.dynv[i+1]); + *ptr = (size_t)&debug; + } } /* This must be done before final relocations, since it calls @@ -2345,7 +2418,7 @@ int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void return ret; } -static void error(const char *fmt, ...) +static void error_impl(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -2359,3 +2432,7 @@ static void error(const char *fmt, ...) __dl_vseterr(fmt, ap); va_end(ap); } + +static void error_noop(const char *fmt, ...) +{ +} 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/complex/cacosf.c b/src/complex/cacosf.c index 2e048540..ed8acf0f 100644 --- a/src/complex/cacosf.c +++ b/src/complex/cacosf.c @@ -2,8 +2,10 @@ // FIXME +static const float float_pi_2 = M_PI_2; + float complex cacosf(float complex z) { z = casinf(z); - return CMPLXF((float)M_PI_2 - crealf(z), -cimagf(z)); + return CMPLXF(float_pi_2 - crealf(z), -cimagf(z)); } diff --git a/src/complex/catanf.c b/src/complex/catanf.c index ef3907a5..1d569f2d 100644 --- a/src/complex/catanf.c +++ b/src/complex/catanf.c @@ -61,13 +61,15 @@ static const double DP1 = 3.140625; static const double DP2 = 9.67502593994140625E-4; static const double DP3 = 1.509957990978376432E-7; +static const float float_pi = M_PI; + static float _redupif(float xx) { float x, t; long i; x = xx; - t = x/(float)M_PI; + t = x/float_pi; if (t >= 0.0f) t += 0.5f; else diff --git a/src/complex/cproj.c b/src/complex/cproj.c index 9ae1e17c..d2b8f5a9 100644 --- a/src/complex/cproj.c +++ b/src/complex/cproj.c @@ -3,6 +3,6 @@ double complex cproj(double complex z) { if (isinf(creal(z)) || isinf(cimag(z))) - return CMPLX(INFINITY, copysign(0.0, creal(z))); + return CMPLX(INFINITY, copysign(0.0, cimag(z))); return z; } diff --git a/src/complex/cprojf.c b/src/complex/cprojf.c index 03fab339..15a874bb 100644 --- a/src/complex/cprojf.c +++ b/src/complex/cprojf.c @@ -3,6 +3,6 @@ float complex cprojf(float complex z) { if (isinf(crealf(z)) || isinf(cimagf(z))) - return CMPLXF(INFINITY, copysignf(0.0, crealf(z))); + return CMPLXF(INFINITY, copysignf(0.0, cimagf(z))); return z; } diff --git a/src/complex/cprojl.c b/src/complex/cprojl.c index 38a494c5..531ffa1c 100644 --- a/src/complex/cprojl.c +++ b/src/complex/cprojl.c @@ -9,7 +9,7 @@ long double complex cprojl(long double complex z) long double complex cprojl(long double complex z) { if (isinf(creall(z)) || isinf(cimagl(z))) - return CMPLXL(INFINITY, copysignl(0.0, creall(z))); + return CMPLXL(INFINITY, copysignl(0.0, cimagl(z))); return z; } #endif diff --git a/src/conf/confstr.c b/src/conf/confstr.c index 02cb1aa2..3d417284 100644 --- a/src/conf/confstr.c +++ b/src/conf/confstr.c @@ -7,7 +7,7 @@ size_t confstr(int name, char *buf, size_t len) const char *s = ""; if (!name) { s = "/bin:/usr/bin"; - } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>33U) { + } else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>35U) { errno = EINVAL; return 0; } 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/ctype/nonspacing.h b/src/ctype/nonspacing.h index 5d05a3d1..7746f3b6 100644 --- a/src/ctype/nonspacing.h +++ b/src/ctype/nonspacing.h @@ -1,23 +1,23 @@ -16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,16,16,32,16,16,16,33,34,35, -36,37,38,39,16,16,40,16,16,16,16,16,16,16,16,16,16,16,41,42,16,16,43,16,16,16, +16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,16,33,16,16,16,34,35,36, +37,38,39,40,16,16,41,16,16,16,16,16,16,16,16,16,16,16,42,43,16,16,44,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,16,16,16,44,16,45,46,47,48,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,45,16,46,47,48,49,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,50,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,51,16,16,52, +53,16,54,55,56,16,16,16,16,16,16,57,16,16,58,16,59,60,61,62,63,64,65,66,67,68, +69,70,16,71,72,73,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,74,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,49,16,16,50, -51,16,52,53,54,16,16,16,16,16,16,55,16,16,56,16,57,58,59,60,61,62,63,64,65,66, -67,68,16,69,70,71,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,72,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,75,76,16,16,16,77,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,73,74,16,16,16,75,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,16,16,16,16,16,76,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, -16,16,77,78,16,16,16,16,16,16,16,79,16,16,16,16,16,80,81,82,16,16,16,16,16,83, -84,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,16,16,16,16,16,78,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, +16,16,79,80,16,16,16,16,16,16,16,81,16,16,16,16,16,82,83,84,16,16,16,16,16,85, +86,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, @@ -35,55 +35,57 @@ 242,7,128,127,0,0,0,0,0,0,0,0,0,0,0,0,242,31,0,63,0,0,0,0,0,0,0,0,0,3,0,0,160, 2,0,0,0,0,0,0,254,127,223,224,255,254,255,255,255,31,64,0,0,0,0,0,0,0,0,0,0,0, 0,224,253,102,0,0,0,195,1,0,30,0,100,32,0,32,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0, -0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254,15,32,0,0,0,0,0,120,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,1,4,14,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,9,0,0,0,0,0,0,64,127, -229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0,15,0,0,0,0,0,208,23,4,0,0, -0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0,0,0,0,0,240,207,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255, +0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,28,0,0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254, +15,32,0,0,0,0,0,120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,135,1,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +128,9,0,0,0,0,0,0,64,127,229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0, +15,0,0,0,0,0,208,23,4,0,0,0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0, +0,0,0,0,240,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255, 251,0,248,0,0,0,124,0,0,0,0,0,0,223,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255, 255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0, 0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,128,247,63,0,0,0,192,0,0,0,0,0,0,0,0,0,0,3,0,68,8,0,0,96,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,255,255,3,128,0,0,0,0,192,63,0,0,128,255,3,0, -0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0,0,0,0,0,0,0,126,102,0,8,16,0,0,0,0, -0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,64, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255,255,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,110,240,0,0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0, -0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,192,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255, -127,0,0,0,0,0,0,128,3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0, -0,0,0,0,0,0,8,0,3,0,0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192, -31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0, -0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,60,176,1,0,0,48,0,0,0, -0,0,0,0,0,0,0,248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0, -0,224,188,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -128,255,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0, -126,14,0,0,0,0,0,252,127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0, -0,0,0,0,0,0,0,252,255,255,252,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,180,191,0, -0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,24, -0,0,0,0,0,0,0,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0, -0,128,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,255,255,255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248, -254,255,0,0,0,0,0,0,0,0,0, -0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0, +0,0,0,0,0,0,126,102,0,8,16,0,0,0,0,0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,0,0,0, +64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255, +255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,1,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,240,0, +0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,240,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,255,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255,127,0,0,0,0,0,0,128, +3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0,0,0,0,0,0,0,8,0,3,0, +0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192,31,31,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0,0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,176,1,0,0,48,0,0,0,0,0,0,0,0,0,0, +248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0,0,224,188,15,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,255,6,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0,126,14,0,0,0,0,0,252, +127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0,0,0,0,0,0,0,0,252,255, +255,252,109,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,126,180,191,0,0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,255, +1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,128,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255, +255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248,254,255,0,0,0, +0,0,0,0,0,0,0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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/env/__stack_chk_fail.c b/src/env/__stack_chk_fail.c index bf5a280a..e5352602 100644 --- a/src/env/__stack_chk_fail.c +++ b/src/env/__stack_chk_fail.c @@ -9,6 +9,15 @@ void __init_ssp(void *entropy) if (entropy) memcpy(&__stack_chk_guard, entropy, sizeof(uintptr_t)); else __stack_chk_guard = (uintptr_t)&__stack_chk_guard * 1103515245; +#if UINTPTR_MAX >= 0xffffffffffffffff + /* Sacrifice 8 bits of entropy on 64bit to prevent leaking/ + * overwriting the canary via string-manipulation functions. + * The NULL byte is on the second byte so that off-by-ones can + * still be detected. Endianness is taken care of + * automatically. */ + ((char *)&__stack_chk_guard)[1] = 0; +#endif + __pthread_self()->canary = __stack_chk_guard; } diff --git a/src/errno/__strerror.h b/src/errno/__strerror.h index 2d992da5..14925907 100644 --- a/src/errno/__strerror.h +++ b/src/errno/__strerror.h @@ -102,3 +102,7 @@ E(EDQUOT, "Quota exceeded") E(ENOMEDIUM, "No medium found") E(EMEDIUMTYPE, "Wrong medium type") E(EMULTIHOP, "Multihop attempted") +E(ENOKEY, "Required key not available") +E(EKEYEXPIRED, "Key has expired") +E(EKEYREVOKED, "Key has been revoked") +E(EKEYREJECTED, "Key was rejected by service") 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/include/stdlib.h b/src/include/stdlib.h index e9da2015..812b04de 100644 --- a/src/include/stdlib.h +++ b/src/include/stdlib.h @@ -8,6 +8,7 @@ hidden void __env_rm_add(char *, char *); hidden int __mkostemps(char *, int, int); hidden int __ptsname_r(int, char *, size_t); hidden char *__randname(char *); +hidden void __qsort_r (void *, size_t, size_t, int (*)(const void *, const void *, void *), void *); hidden void *__libc_malloc(size_t); hidden void *__libc_malloc_impl(size_t); diff --git a/src/include/sys/stat.h b/src/include/sys/stat.h new file mode 100644 index 00000000..59339bee --- /dev/null +++ b/src/include/sys/stat.h @@ -0,0 +1,9 @@ +#ifndef SYS_STAT_H +#define SYS_STAT_H + +#include "../../../include/sys/stat.h" + +hidden int __fstat(int, struct stat *); +hidden int __fstatat(int, const char *restrict, struct stat *restrict, int); + +#endif diff --git a/src/internal/dynlink.h b/src/internal/dynlink.h index 51c0639f..06f41d09 100644 --- a/src/internal/dynlink.h +++ b/src/internal/dynlink.h @@ -92,8 +92,12 @@ struct fdpic_dummy_loadmap { #define DT_DEBUG_INDIRECT 0 #endif +#ifndef DT_DEBUG_INDIRECT_REL +#define DT_DEBUG_INDIRECT_REL 0 +#endif + #define AUX_CNT 32 -#define DYN_CNT 32 +#define DYN_CNT 37 typedef void (*stage2_func)(unsigned char *, size_t *); 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/internal/ksigaction.h b/src/internal/ksigaction.h index 8ebd5938..ef333f33 100644 --- a/src/internal/ksigaction.h +++ b/src/internal/ksigaction.h @@ -6,8 +6,13 @@ struct k_sigaction { void (*handler)(int); unsigned long flags; +#ifdef SA_RESTORER void (*restorer)(void); +#endif unsigned mask[2]; +#ifndef SA_RESTORER + void *unused; +#endif }; hidden void __restore(), __restore_rt(); diff --git a/src/internal/syscall.h b/src/internal/syscall.h index d5f294d4..4a446157 100644 --- a/src/internal/syscall.h +++ b/src/internal/syscall.h @@ -58,7 +58,7 @@ hidden long __syscall_ret(unsigned long), #define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) -static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, long c, long d, long e, long f) +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) { long r; if (cp) r = __syscall_cp(sys, a, b, c, d, e, f); @@ -71,9 +71,9 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l return r; } #define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \ - (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) + __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f)) #define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \ - (long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f)) + __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f)) /* fixup legacy 16-bit junk */ @@ -201,43 +201,43 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l #define SYS_sendfile SYS_sendfile64 #endif -#ifndef SYS_timer_settime +#ifdef SYS_timer_settime32 #define SYS_timer_settime SYS_timer_settime32 #endif -#ifndef SYS_timer_gettime +#ifdef SYS_timer_gettime32 #define SYS_timer_gettime SYS_timer_gettime32 #endif -#ifndef SYS_timerfd_settime +#ifdef SYS_timerfd_settime32 #define SYS_timerfd_settime SYS_timerfd_settime32 #endif -#ifndef SYS_timerfd_gettime +#ifdef SYS_timerfd_gettime32 #define SYS_timerfd_gettime SYS_timerfd_gettime32 #endif -#ifndef SYS_clock_settime +#ifdef SYS_clock_settime32 #define SYS_clock_settime SYS_clock_settime32 #endif -#ifndef SYS_clock_gettime +#ifdef SYS_clock_gettime32 #define SYS_clock_gettime SYS_clock_gettime32 #endif -#ifndef SYS_clock_getres +#ifdef SYS_clock_getres_time32 #define SYS_clock_getres SYS_clock_getres_time32 #endif -#ifndef SYS_clock_nanosleep +#ifdef SYS_clock_nanosleep_time32 #define SYS_clock_nanosleep SYS_clock_nanosleep_time32 #endif -#ifndef SYS_gettimeofday +#ifdef SYS_gettimeofday_time32 #define SYS_gettimeofday SYS_gettimeofday_time32 #endif -#ifndef SYS_settimeofday +#ifdef SYS_settimeofday_time32 #define SYS_settimeofday SYS_settimeofday_time32 #endif 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/locale/dcngettext.c b/src/locale/dcngettext.c index d1e6c6d1..0b53286d 100644 --- a/src/locale/dcngettext.c +++ b/src/locale/dcngettext.c @@ -132,6 +132,9 @@ char *dcngettext(const char *domainname, const char *msgid1, const char *msgid2, struct binding *q; int old_errno = errno; + /* match gnu gettext behaviour */ + if (!msgid1) goto notrans; + if ((unsigned)category >= LC_ALL) goto notrans; if (!domainname) domainname = __gettextdomain(); diff --git a/src/locale/duplocale.c b/src/locale/duplocale.c index 030b64cb..5ce33ae6 100644 --- a/src/locale/duplocale.c +++ b/src/locale/duplocale.c @@ -3,6 +3,11 @@ #include "locale_impl.h" #include "libc.h" +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef + locale_t __duplocale(locale_t old) { locale_t new = malloc(sizeof *new); diff --git a/src/locale/strtod_l.c b/src/locale/strtod_l.c new file mode 100644 index 00000000..574ba148 --- /dev/null +++ b/src/locale/strtod_l.c @@ -0,0 +1,22 @@ +#define _GNU_SOURCE +#include <stdlib.h> +#include <locale.h> + +float strtof_l(const char *restrict s, char **restrict p, locale_t l) +{ + return strtof(s, p); +} + +double strtod_l(const char *restrict s, char **restrict p, locale_t l) +{ + return strtod(s, p); +} + +long double strtold_l(const char *restrict s, char **restrict p, locale_t l) +{ + return strtold(s, p); +} + +weak_alias(strtof_l, __strtof_l); +weak_alias(strtod_l, __strtod_l); +weak_alias(strtold_l, __strtold_l); 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/math/logf.c b/src/math/logf.c index 7ee5d7fe..e4c2237c 100644 --- a/src/math/logf.c +++ b/src/math/logf.c @@ -53,7 +53,7 @@ float logf(float x) tmp = ix - OFF; i = (tmp >> (23 - LOGF_TABLE_BITS)) % N; k = (int32_t)tmp >> 23; /* arithmetic shift */ - iz = ix - (tmp & 0x1ff << 23); + iz = ix - (tmp & 0xff800000); invc = T[i].invc; logc = T[i].logc; z = (double_t)asfloat(iz); diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c index 2ab2f0f4..a5558d81 100644 --- a/src/misc/getrlimit.c +++ b/src/misc/getrlimit.c @@ -6,12 +6,13 @@ int getrlimit(int resource, struct rlimit *rlim) { - unsigned long k_rlim[2]; int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim); if (!ret) { FIX(rlim->rlim_cur); FIX(rlim->rlim_max); } +#ifdef SYS_getrlimit + unsigned long k_rlim[2]; if (!ret || errno != ENOSYS) return ret; if (syscall(SYS_getrlimit, resource, k_rlim) < 0) @@ -21,6 +22,7 @@ int getrlimit(int resource, struct rlimit *rlim) FIX(rlim->rlim_cur); FIX(rlim->rlim_max); return 0; +#else + return ret; +#endif } - -weak_alias(getrlimit, getrlimit64); diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c index 49282811..35804f02 100644 --- a/src/misc/ioctl.c +++ b/src/misc/ioctl.c @@ -6,6 +6,7 @@ #include <stddef.h> #include <stdint.h> #include <string.h> +#include <endian.h> #include "syscall.h" #define alignof(t) offsetof(struct { char c; t x; }, x) @@ -53,7 +54,7 @@ static const struct ioctl_compat_map compat_map[] = { { _IOWR('A', 0x23, char[136]), _IOWR('A', 0x23, char[132]), 0, WR, 1, 0 }, { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_sync_ptr (flags only) */ { 0, 0, 32, WR, 1, OFFS(8,12,16,24,28) }, /* snd_pcm_mmap_status */ - { 0, 0, 8, WR, 1, OFFS(0,4) }, /* snd_pcm_mmap_control */ + { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_mmap_control (each member) */ /* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */ { _IOWR('V', 9, new_misaligned(68)), _IOWR('V', 9, char[68]), 68, WR, 1, OFFS(20, 24) }, @@ -90,7 +91,11 @@ static void convert_ioctl_struct(const struct ioctl_compat_map *map, char *old, * if another exception appears this needs changing. */ convert_ioctl_struct(map+1, old, new, dir); convert_ioctl_struct(map+2, old+4, new+8, dir); - convert_ioctl_struct(map+3, old+68, new+72, dir); + /* snd_pcm_mmap_control, special-cased due to kernel + * type definition having been botched. */ + int adj = BYTE_ORDER==BIG_ENDIAN ? 4 : 0; + convert_ioctl_struct(map+3, old+68, new+72+adj, dir); + convert_ioctl_struct(map+3, old+72, new+76+3*adj, dir); return; } for (int i=0; i < map->noffs; i++) { 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/mntent.c b/src/misc/mntent.c index eabb8200..d404fbe3 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -2,6 +2,7 @@ #include <string.h> #include <mntent.h> #include <errno.h> +#include <limits.h> static char *internal_buf; static size_t internal_bufsize; @@ -21,7 +22,8 @@ int endmntent(FILE *f) struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen) { - int cnt, n[8], use_internal = (linebuf == SENTINEL); + int n[8], use_internal = (linebuf == SENTINEL); + size_t len, i; mnt->mnt_freq = 0; mnt->mnt_passno = 0; @@ -39,10 +41,14 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle errno = ERANGE; return 0; } - cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", + + len = strlen(linebuf); + if (len > INT_MAX) continue; + for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len; + sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", n, n+1, n+2, n+3, n+4, n+5, n+6, n+7, &mnt->mnt_freq, &mnt->mnt_passno); - } while (cnt < 2 || linebuf[n[0]] == '#'); + } while (linebuf[n[0]] == '#' || n[1]==len); linebuf[n[1]] = 0; linebuf[n[3]] = 0; 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 8340aee0..edb413fa 100644 --- a/src/misc/setrlimit.c +++ b/src/misc/setrlimit.c @@ -12,12 +12,14 @@ struct ctx { int err; }; +#ifdef SYS_setrlimit static void do_setrlimit(void *p) { struct ctx *c = p; if (c->err>0) return; c->err = -__syscall(SYS_setrlimit, c->res, c->lim); } +#endif int setrlimit(int resource, const struct rlimit *rlim) { @@ -29,6 +31,7 @@ int setrlimit(int resource, const struct rlimit *rlim) rlim = &tmp; } int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0); +#ifdef SYS_setrlimit if (ret != -ENOSYS) return __syscall_ret(ret); struct ctx c = { @@ -42,6 +45,7 @@ int setrlimit(int resource, const struct rlimit *rlim) return -1; } return 0; +#else + 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/mq/mq_notify.c b/src/mq/mq_notify.c index 221591c7..0e1e6c7a 100644 --- a/src/mq/mq_notify.c +++ b/src/mq/mq_notify.c @@ -4,11 +4,14 @@ #include <sys/socket.h> #include <signal.h> #include <unistd.h> +#include <semaphore.h> #include "syscall.h" struct args { - pthread_barrier_t barrier; + sem_t sem; int sock; + mqd_t mqd; + int err; const struct sigevent *sev; }; @@ -20,8 +23,19 @@ static void *start(void *p) int s = args->sock; void (*func)(union sigval) = args->sev->sigev_notify_function; union sigval val = args->sev->sigev_value; + struct sigevent sev2; + static const char zeros[32]; + int err; + + sev2.sigev_notify = SIGEV_THREAD; + sev2.sigev_signo = s; + sev2.sigev_value.sival_ptr = (void *)&zeros; + + args->err = err = -__syscall(SYS_mq_notify, args->mqd, &sev2); + sem_post(&args->sem); + if (err) return 0; - pthread_barrier_wait(&args->barrier); + pthread_detach(pthread_self()); n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL); close(s); if (n==sizeof buf && buf[sizeof buf - 1] == 1) @@ -35,8 +49,8 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) pthread_attr_t attr; pthread_t td; int s; - struct sigevent sev2; - static const char zeros[32]; + int cs; + sigset_t allmask, origmask; if (!sev || sev->sigev_notify != SIGEV_THREAD) return syscall(SYS_mq_notify, mqd, sev); @@ -44,30 +58,35 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0); if (s < 0) return -1; args.sock = s; + args.mqd = mqd; if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes; else pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_barrier_init(&args.barrier, 0, 2); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + sem_init(&args.sem, 0, 0); + sigfillset(&allmask); + pthread_sigmask(SIG_BLOCK, &allmask, &origmask); if (pthread_create(&td, &attr, start, &args)) { __syscall(SYS_close, s); + pthread_sigmask(SIG_SETMASK, &origmask, 0); errno = EAGAIN; return -1; } + pthread_sigmask(SIG_SETMASK, &origmask, 0); - pthread_barrier_wait(&args.barrier); - pthread_barrier_destroy(&args.barrier); - - sev2.sigev_notify = SIGEV_THREAD; - sev2.sigev_signo = s; - sev2.sigev_value.sival_ptr = (void *)&zeros; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + sem_wait(&args.sem); + sem_destroy(&args.sem); - if (syscall(SYS_mq_notify, mqd, &sev2) < 0) { - pthread_cancel(td); + if (args.err) { __syscall(SYS_close, s); + pthread_join(td, 0); + pthread_setcancelstate(cs, 0); + errno = args.err; return -1; } + pthread_setcancelstate(cs, 0); return 0; } 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 efaab306..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; @@ -66,9 +67,11 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &cs); int r = connect(s, ta[i], tl[i]); + int saved_errno = errno; pthread_setcancelstate(cs, 0); close(s); if (!r) continue; + errno = saved_errno; } switch (errno) { case EADDRNOTAVAIL: @@ -80,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]; } } @@ -91,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/inet_pton.c b/src/network/inet_pton.c index d36c3689..bcbdd9ef 100644 --- a/src/network/inet_pton.c +++ b/src/network/inet_pton.c @@ -54,6 +54,7 @@ int inet_pton(int af, const char *restrict s, void *restrict a0) if (s[j]!='.' || (i<6 && brk<0)) return 0; need_v4=1; i++; + ip[i&7]=0; break; } s += j+1; 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 aa558c19..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,8 +158,12 @@ 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]) + qbuf[nq][0]++; nq++; } } @@ -168,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/netlink.h b/src/network/netlink.h index 38acb178..873fabe2 100644 --- a/src/network/netlink.h +++ b/src/network/netlink.h @@ -86,7 +86,7 @@ struct ifaddrmsg { #define RTA_DATALEN(rta) ((rta)->rta_len-sizeof(struct rtattr)) #define RTA_DATAEND(rta) ((char*)(rta)+(rta)->rta_len) #define RTA_NEXT(rta) (struct rtattr*)((char*)(rta)+NETLINK_ALIGN((rta)->rta_len)) -#define RTA_OK(nlh,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr)) +#define RTA_OK(rta,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr)) #define NLMSG_RTA(nlh,len) ((void*)((char*)(nlh)+sizeof(struct nlmsghdr)+NETLINK_ALIGN(len))) #define NLMSG_RTAOK(rta,nlh) RTA_OK(rta,NLMSG_DATAEND(nlh)) 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..fef7e3a2 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,17 +17,65 @@ 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() { struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0 && errno == ENOSYS) + clock_gettime(CLOCK_REALTIME, &ts); return (unsigned long)ts.tv_sec * 1000 + 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 +93,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 +120,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 +144,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 +169,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 +193,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 +246,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/network/sendmsg.c b/src/network/sendmsg.c index 80cc5f41..acdfdf29 100644 --- a/src/network/sendmsg.c +++ b/src/network/sendmsg.c @@ -8,13 +8,16 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) { #if LONG_MAX > INT_MAX struct msghdr h; - struct cmsghdr chbuf[1024/sizeof(struct cmsghdr)+1], *c; + /* Kernels before 2.6.38 set SCM_MAX_FD to 255, allocate enough + * space to support an SCM_RIGHTS ancillary message with 255 fds. + * Kernels since 2.6.38 set SCM_MAX_FD to 253. */ + struct cmsghdr chbuf[CMSG_SPACE(255*sizeof(int))/sizeof(struct cmsghdr)+1], *c; if (msg) { h = *msg; h.__pad1 = h.__pad2 = 0; msg = &h; if (h.msg_controllen) { - if (h.msg_controllen > 1024) { + if (h.msg_controllen > sizeof chbuf) { errno = ENOMEM; return -1; } 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/aarch64/vfork.s b/src/process/aarch64/vfork.s new file mode 100644 index 00000000..429bec8c --- /dev/null +++ b/src/process/aarch64/vfork.s @@ -0,0 +1,9 @@ +.global vfork +.type vfork,%function +vfork: + mov x8, 220 // SYS_clone + mov x0, 0x4111 // SIGCHLD | CLONE_VM | CLONE_VFORK + mov x1, 0 + svc 0 + .hidden __syscall_ret + b __syscall_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/process/riscv64/vfork.s b/src/process/riscv64/vfork.s new file mode 100644 index 00000000..c93dca23 --- /dev/null +++ b/src/process/riscv64/vfork.s @@ -0,0 +1,12 @@ +.global vfork +.type vfork,@function +vfork: + /* riscv does not have SYS_vfork, so we must use clone instead */ + /* note: riscv's clone = clone(flags, sp, ptidptr, tls, ctidptr) */ + li a7, 220 + li a0, 0x100 | 0x4000 | 17 /* flags = CLONE_VM | CLONE_VFORK | SIGCHLD */ + mv a1, sp + /* the other arguments are ignoreable */ + ecall + .hidden __syscall_ret + j __syscall_ret 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/search/hsearch.c b/src/search/hsearch.c index b3ac8796..2634a67f 100644 --- a/src/search/hsearch.c +++ b/src/search/hsearch.c @@ -41,9 +41,9 @@ static int resize(size_t nel, struct hsearch_data *htab) { size_t newsize; size_t i, j; + size_t oldsize = htab->__tab->mask + 1; ENTRY *e, *newe; ENTRY *oldtab = htab->__tab->entries; - ENTRY *oldend = htab->__tab->entries + htab->__tab->mask + 1; if (nel > MAXSIZE) nel = MAXSIZE; @@ -56,7 +56,7 @@ static int resize(size_t nel, struct hsearch_data *htab) htab->__tab->mask = newsize - 1; if (!oldtab) return 1; - for (e = oldtab; e < oldend; e++) + for (e = oldtab; e < oldtab + oldsize; e++) if (e->key) { for (i=keyhash(e->key),j=1; ; i+=j++) { newe = htab->__tab->entries + (i & htab->__tab->mask); diff --git a/src/setjmp/powerpc/longjmp.S b/src/setjmp/powerpc/longjmp.S index 34aecb4c..465e4cd7 100644 --- a/src/setjmp/powerpc/longjmp.S +++ b/src/setjmp/powerpc/longjmp.S @@ -42,10 +42,10 @@ longjmp: bl 1f .hidden __hwcap .long __hwcap-. -1: mflr 4 - lwz 5, 0(4) - add 4, 4, 5 - andis. 4, 4, 0x80 +1: mflr 6 + lwz 5, 0(6) + lwzx 6, 6, 5 + andis. 6, 6, 0x80 beq 1f .long 0x11c35b01 /* evldd 14,88(3) */ .long 0x11e36301 /* ... */ diff --git a/src/setjmp/powerpc/setjmp.S b/src/setjmp/powerpc/setjmp.S index 413e6a81..f1fcce33 100644 --- a/src/setjmp/powerpc/setjmp.S +++ b/src/setjmp/powerpc/setjmp.S @@ -44,7 +44,7 @@ setjmp: .long __hwcap-. 1: mflr 4 lwz 5, 0(4) - add 4, 4, 5 + lwzx 4, 4, 5 andis. 4, 4, 0x80 beq 1f .long 0x11c35b21 /* evstdd 14,88(3) */ diff --git a/src/signal/mips/restore.s b/src/signal/mips/restore.s deleted file mode 100644 index b6dadce0..00000000 --- a/src/signal/mips/restore.s +++ /dev/null @@ -1,15 +0,0 @@ -.set noreorder - -.global __restore_rt -.hidden __restore_rt -.type __restore_rt,@function -__restore_rt: - li $2, 4193 - syscall - -.global __restore -.hidden __restore -.type __restore,@function -__restore: - li $2, 4119 - syscall diff --git a/src/signal/mips64/restore.s b/src/signal/mips64/restore.s deleted file mode 100644 index 401f8e73..00000000 --- a/src/signal/mips64/restore.s +++ /dev/null @@ -1,11 +0,0 @@ -.set noreorder -.global __restore_rt -.global __restore -.hidden __restore_rt -.hidden __restore -.type __restore_rt,@function -.type __restore,@function -__restore_rt: -__restore: - li $2,5211 - syscall diff --git a/src/signal/mipsn32/restore.s b/src/signal/mipsn32/restore.s deleted file mode 100644 index 4cd4e1b4..00000000 --- a/src/signal/mipsn32/restore.s +++ /dev/null @@ -1,11 +0,0 @@ -.set noreorder -.global __restore_rt -.global __restore -.hidden __restore_rt -.hidden __restore -.type __restore_rt,@function -.type __restore,@function -__restore_rt: -__restore: - li $2,6211 - syscall diff --git a/src/signal/sigaction.c b/src/signal/sigaction.c index 2203471b..e45308fa 100644 --- a/src/signal/sigaction.c +++ b/src/signal/sigaction.c @@ -44,8 +44,11 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact } } ksa.handler = sa->sa_handler; - ksa.flags = sa->sa_flags | SA_RESTORER; + ksa.flags = sa->sa_flags; +#ifdef SA_RESTORER + ksa.flags |= SA_RESTORER; ksa.restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore; +#endif memcpy(&ksa.mask, &sa->sa_mask, _NSIG/8); } int r = __syscall(SYS_rt_sigaction, sig, sa?&ksa:0, old?&ksa_old:0, _NSIG/8); 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/fchmodat.c b/src/stat/fchmodat.c index 4ee00b0a..bc581050 100644 --- a/src/stat/fchmodat.c +++ b/src/stat/fchmodat.c @@ -2,7 +2,6 @@ #include <fcntl.h> #include <errno.h> #include "syscall.h" -#include "kstat.h" int fchmodat(int fd, const char *path, mode_t mode, int flag) { @@ -11,12 +10,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) if (flag != AT_SYMLINK_NOFOLLOW) return __syscall_ret(-EINVAL); - struct kstat st; + struct stat st; int ret, fd2; char proc[15+3*sizeof(int)]; - if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag))) - return __syscall_ret(ret); + if (fstatat(fd, path, &st, flag)) + return -1; if (S_ISLNK(st.st_mode)) return __syscall_ret(-EOPNOTSUPP); @@ -27,12 +26,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag) } __procfdname(proc, fd2); - ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0); + ret = stat(proc, &st); if (!ret) { - if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP; - else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode); + if (S_ISLNK(st.st_mode)) ret = __syscall_ret(-EOPNOTSUPP); + else ret = syscall(SYS_fchmodat, AT_FDCWD, proc, mode); } __syscall(SYS_close, fd2); - return __syscall_ret(ret); + return ret; } diff --git a/src/stat/fstat.c b/src/stat/fstat.c index 9bbb46de..fd28b8ac 100644 --- a/src/stat/fstat.c +++ b/src/stat/fstat.c @@ -4,12 +4,10 @@ #include <fcntl.h> #include "syscall.h" -int fstat(int fd, struct stat *st) +int __fstat(int fd, struct stat *st) { if (fd<0) return __syscall_ret(-EBADF); - return fstatat(fd, "", st, AT_EMPTY_PATH); + return __fstatat(fd, "", st, AT_EMPTY_PATH); } -#if !_REDIR_TIME64 -weak_alias(fstat, fstat64); -#endif +weak_alias(__fstat, fstat); diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index de165b5c..04506375 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -6,7 +6,6 @@ #include <stdint.h> #include <sys/sysmacros.h> #include "syscall.h" -#include "kstat.h" struct statx { uint32_t stx_mask; @@ -69,6 +68,10 @@ static int fstatat_statx(int fd, const char *restrict path, struct stat *restric return 0; } +#ifdef SYS_fstatat + +#include "kstat.h" + static int fstatat_kstat(int fd, const char *restrict path, struct stat *restrict st, int flag) { int ret; @@ -130,18 +133,21 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric return 0; } +#endif -int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) +int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) { int ret; +#ifdef SYS_fstatat if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) { ret = fstatat_statx(fd, path, st, flag); if (ret!=-ENOSYS) return __syscall_ret(ret); } ret = fstatat_kstat(fd, path, st, flag); +#else + ret = fstatat_statx(fd, path, st, flag); +#endif return __syscall_ret(ret); } -#if !_REDIR_TIME64 -weak_alias(fstatat, fstatat64); -#endif +weak_alias(__fstatat, fstatat); 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/fgetws.c b/src/stdio/fgetws.c index b08b3049..195cb435 100644 --- a/src/stdio/fgetws.c +++ b/src/stdio/fgetws.c @@ -1,6 +1,5 @@ #include "stdio_impl.h" #include <wchar.h> -#include <errno.h> wint_t __fgetwc_unlocked(FILE *); @@ -12,10 +11,6 @@ wchar_t *fgetws(wchar_t *restrict s, int n, FILE *restrict f) FLOCK(f); - /* Setup a dummy errno so we can detect EILSEQ. This is - * the only way to catch encoding errors in the form of a - * partial character just before EOF. */ - errno = EAGAIN; for (; n; n--) { wint_t c = __fgetwc_unlocked(f); if (c == WEOF) break; @@ -23,7 +18,7 @@ wchar_t *fgetws(wchar_t *restrict s, int n, FILE *restrict f) if (c == '\n') break; } *p = 0; - if (ferror(f) || errno==EILSEQ) p = s; + if (ferror(f)) p = s; FUNLOCK(f); 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 439308f7..c7425802 100644 --- a/src/stdio/fseek.c +++ b/src/stdio/fseek.c @@ -1,7 +1,14 @@ #include "stdio_impl.h" +#include <errno.h> int __fseeko_unlocked(FILE *f, off_t off, int whence) { + /* Fail immediately for invalid whence argument. */ + if (whence != SEEK_CUR && whence != SEEK_SET && whence != SEEK_END) { + errno = EINVAL; + return -1; + } + /* Adjust relative offset for unread data in buffer, if any. */ if (whence == SEEK_CUR && f->rend) off -= f->rend - f->rpos; @@ -39,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/tempnam.c b/src/stdio/tempnam.c index 565df6b6..0c65b1f0 100644 --- a/src/stdio/tempnam.c +++ b/src/stdio/tempnam.c @@ -6,7 +6,6 @@ #include <string.h> #include <stdlib.h> #include "syscall.h" -#include "kstat.h" #define MAXTRIES 100 @@ -37,11 +36,10 @@ char *tempnam(const char *dir, const char *pfx) for (try=0; try<MAXTRIES; try++) { __randname(s+l-6); -#ifdef SYS_lstat - r = __syscall(SYS_lstat, s, &(struct kstat){0}); +#ifdef SYS_readlink + r = __syscall(SYS_readlink, s, (char[1]){0}, 1); #else - r = __syscall(SYS_fstatat, AT_FDCWD, s, - &(struct kstat){0}, AT_SYMLINK_NOFOLLOW); + r = __syscall(SYS_readlinkat, AT_FDCWD, s, (char[1]){0}, 1); #endif if (r == -ENOENT) return strdup(s); } 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/stdio/tmpnam.c b/src/stdio/tmpnam.c index d667a836..71dc8bb1 100644 --- a/src/stdio/tmpnam.c +++ b/src/stdio/tmpnam.c @@ -5,7 +5,6 @@ #include <string.h> #include <stdlib.h> #include "syscall.h" -#include "kstat.h" #define MAXTRIES 100 @@ -17,11 +16,10 @@ char *tmpnam(char *buf) int r; for (try=0; try<MAXTRIES; try++) { __randname(s+12); -#ifdef SYS_lstat - r = __syscall(SYS_lstat, s, &(struct kstat){0}); +#ifdef SYS_readlink + r = __syscall(SYS_readlink, s, (char[1]){0}, 1); #else - r = __syscall(SYS_fstatat, AT_FDCWD, s, - &(struct kstat){0}, AT_SYMLINK_NOFOLLOW); + r = __syscall(SYS_readlinkat, AT_FDCWD, s, (char[1]){0}, 1); #endif if (r == -ENOENT) return strcpy(buf ? buf : internal, s); } diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index 9b961e7f..45557951 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -478,8 +478,8 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (*s=='*') { if (isdigit(s[1]) && s[2]=='$') { l10n=1; - nl_type[s[1]-'0'] = INT; - w = nl_arg[s[1]-'0'].i; + if (!f) nl_type[s[1]-'0'] = INT, w = 0; + else w = nl_arg[s[1]-'0'].i; s+=3; } else if (!l10n) { w = f ? va_arg(*ap, int) : 0; @@ -491,8 +491,8 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, /* Read precision */ if (*s=='.' && s[1]=='*') { if (isdigit(s[2]) && s[3]=='$') { - nl_type[s[2]-'0'] = INT; - p = nl_arg[s[2]-'0'].i; + if (!f) nl_type[s[2]-'0'] = INT, p = 0; + else p = nl_arg[s[2]-'0'].i; s+=4; } else if (!l10n) { p = f ? va_arg(*ap, int) : 0; @@ -521,8 +521,10 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, if (st==NOARG) { if (argpos>=0) goto inval; } else { - if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos]; - else if (f) pop_arg(&arg, st, ap); + if (argpos>=0) { + if (!f) nl_type[argpos]=st; + else arg=nl_arg[argpos]; + } else if (f) pop_arg(&arg, st, ap); else return 0; } diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c index da58fd31..314ddc29 100644 --- a/src/stdlib/qsort.c +++ b/src/stdlib/qsort.c @@ -24,6 +24,7 @@ /* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1). Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */ +#define _BSD_SOURCE #include <stdint.h> #include <stdlib.h> #include <string.h> @@ -31,7 +32,7 @@ #include "atomic.h" #define ntz(x) a_ctz_l((x)) -typedef int (*cmpfun)(const void *, const void *); +typedef int (*cmpfun)(const void *, const void *, void *); static inline int pntz(size_t p[2]) { int r = ntz(p[0] - 1); @@ -88,7 +89,7 @@ static inline void shr(size_t p[2], int n) p[1] >>= n; } -static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size_t lp[]) +static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[]) { unsigned char *rt, *lf; unsigned char *ar[14 * sizeof(size_t) + 1]; @@ -99,10 +100,10 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size rt = head - width; lf = head - width - lp[pshift - 2]; - if((*cmp)(ar[0], lf) >= 0 && (*cmp)(ar[0], rt) >= 0) { + if(cmp(ar[0], lf, arg) >= 0 && cmp(ar[0], rt, arg) >= 0) { break; } - if((*cmp)(lf, rt) >= 0) { + if(cmp(lf, rt, arg) >= 0) { ar[i++] = lf; head = lf; pshift -= 1; @@ -115,7 +116,7 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, int pshift, size cycle(width, ar, i); } -static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], int pshift, int trusty, size_t lp[]) +static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[]) { unsigned char *stepson, *rt, *lf; @@ -130,13 +131,13 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], ar[0] = head; while(p[0] != 1 || p[1] != 0) { stepson = head - lp[pshift]; - if((*cmp)(stepson, ar[0]) <= 0) { + if(cmp(stepson, ar[0], arg) <= 0) { break; } if(!trusty && pshift > 1) { rt = head - width; lf = head - width - lp[pshift - 2]; - if((*cmp)(rt, stepson) >= 0 || (*cmp)(lf, stepson) >= 0) { + if(cmp(rt, stepson, arg) >= 0 || cmp(lf, stepson, arg) >= 0) { break; } } @@ -150,11 +151,11 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, size_t pp[2], } if(!trusty) { cycle(width, ar, i); - sift(head, width, cmp, pshift, lp); + sift(head, width, cmp, arg, pshift, lp); } } -void qsort(void *base, size_t nel, size_t width, cmpfun cmp) +void __qsort_r(void *base, size_t nel, size_t width, cmpfun cmp, void *arg) { size_t lp[12*sizeof(size_t)]; size_t i, size = width * nel; @@ -173,16 +174,16 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp) while(head < high) { if((p[0] & 3) == 3) { - sift(head, width, cmp, pshift, lp); + sift(head, width, cmp, arg, pshift, lp); shr(p, 2); pshift += 2; } else { if(lp[pshift - 1] >= high - head) { - trinkle(head, width, cmp, p, pshift, 0, lp); + trinkle(head, width, cmp, arg, p, pshift, 0, lp); } else { - sift(head, width, cmp, pshift, lp); + sift(head, width, cmp, arg, pshift, lp); } - + if(pshift == 1) { shl(p, 1); pshift = 0; @@ -191,12 +192,12 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp) pshift = 1; } } - + p[0] |= 1; head += width; } - trinkle(head, width, cmp, p, pshift, 0, lp); + trinkle(head, width, cmp, arg, p, pshift, 0, lp); while(pshift != 1 || p[0] != 1 || p[1] != 0) { if(pshift <= 1) { @@ -208,11 +209,13 @@ void qsort(void *base, size_t nel, size_t width, cmpfun cmp) pshift -= 2; p[0] ^= 7; shr(p, 1); - trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp); + trinkle(head - lp[pshift] - width, width, cmp, arg, p, pshift + 1, 1, lp); shl(p, 1); p[0] |= 1; - trinkle(head - width, width, cmp, p, pshift, 1, lp); + trinkle(head - width, width, cmp, arg, p, pshift, 1, lp); } head -= width; } } + +weak_alias(__qsort_r, qsort_r); diff --git a/src/stdlib/qsort_nr.c b/src/stdlib/qsort_nr.c new file mode 100644 index 00000000..8ffe71d0 --- /dev/null +++ b/src/stdlib/qsort_nr.c @@ -0,0 +1,14 @@ +#define _BSD_SOURCE +#include <stdlib.h> + +typedef int (*cmpfun)(const void *, const void *); + +static int wrapper_cmp(const void *v1, const void *v2, void *cmp) +{ + return ((cmpfun)cmp)(v1, v2); +} + +void qsort(void *base, size_t nel, size_t width, cmpfun cmp) +{ + __qsort_r(base, nel, width, wrapper_cmp, (void *)cmp); +} diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c index a5d0118a..39b9daad 100644 --- a/src/stdlib/strtod.c +++ b/src/stdlib/strtod.c @@ -28,10 +28,3 @@ long double strtold(const char *restrict s, char **restrict p) { return strtox(s, p, 2); } - -weak_alias(strtof, strtof_l); -weak_alias(strtod, strtod_l); -weak_alias(strtold, strtold_l); -weak_alias(strtof, __strtof_l); -weak_alias(strtod, __strtod_l); -weak_alias(strtold, __strtold_l); diff --git a/src/string/strverscmp.c b/src/string/strverscmp.c index 4daf276d..16c1da22 100644 --- a/src/string/strverscmp.c +++ b/src/string/strverscmp.c @@ -18,9 +18,9 @@ int strverscmp(const char *l0, const char *r0) else if (c!='0') z=0; } - if (l[dp]!='0' && r[dp]!='0') { - /* If we're not looking at a digit sequence that began - * with a zero, longest digit string is greater. */ + if (l[dp]-'1'<9U && r[dp]-'1'<9U) { + /* If we're looking at non-degenerate digit sequences starting + * with nonzero digits, longest digit string is greater. */ for (j=i; isdigit(l[j]); j++) if (!isdigit(r[j])) return 1; if (isdigit(r[j])) return -1; diff --git a/src/string/wcscmp.c b/src/string/wcscmp.c index 26eeee70..286ec3ea 100644 --- a/src/string/wcscmp.c +++ b/src/string/wcscmp.c @@ -3,5 +3,5 @@ int wcscmp(const wchar_t *l, const wchar_t *r) { for (; *l==*r && *l && *r; l++, r++); - return *l - *r; + return *l < *r ? -1 : *l > *r; } diff --git a/src/string/wcsncmp.c b/src/string/wcsncmp.c index 4ab32a92..2b3558bf 100644 --- a/src/string/wcsncmp.c +++ b/src/string/wcsncmp.c @@ -3,5 +3,5 @@ int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n) { for (; n && *l==*r && *l && *r; n--, l++, r++); - return n ? *l - *r : 0; + return n ? (*l < *r ? -1 : *l > *r) : 0; } diff --git a/src/temp/__randname.c b/src/temp/__randname.c index 2bce37a0..e9b970f1 100644 --- a/src/temp/__randname.c +++ b/src/temp/__randname.c @@ -1,5 +1,6 @@ #include <time.h> #include <stdint.h> +#include "pthread_impl.h" /* This assumes that a check for the template size has already been made */ @@ -10,7 +11,7 @@ char *__randname(char *template) unsigned long r; __clock_gettime(CLOCK_REALTIME, &ts); - r = ts.tv_nsec*65537 ^ (uintptr_t)&ts / 16 + (uintptr_t)template; + r = ts.tv_sec + ts.tv_nsec + __pthread_self()->tid * 65537UL; for (i=0; i<6; i++, r>>=5) template[i] = 'A'+(r&15)+(r&16)*2; 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_atfork.c b/src/thread/pthread_atfork.c index 76497401..26d32543 100644 --- a/src/thread/pthread_atfork.c +++ b/src/thread/pthread_atfork.c @@ -1,7 +1,13 @@ #include <pthread.h> +#include <errno.h> #include "libc.h" #include "lock.h" +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef + static struct atfork_funcs { void (*prepare)(void); void (*parent)(void); @@ -34,7 +40,7 @@ void __fork_handler(int who) int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) { struct atfork_funcs *new = malloc(sizeof *new); - if (!new) return -1; + if (!new) return ENOMEM; LOCK(lock); new->next = funcs; diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c index 2f9d5e97..139a6fc8 100644 --- a/src/thread/pthread_cancel.c +++ b/src/thread/pthread_cancel.c @@ -56,7 +56,12 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx) _sigaddset(&uc->uc_sigmask, SIGCANCEL); - if (self->cancelasync || pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) { + if (self->cancelasync) { + pthread_sigmask(SIG_SETMASK, &uc->uc_sigmask, 0); + __cancel(); + } + + if (pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) { uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel; #ifdef CANCEL_GOT uc->uc_mcontext.MC_GOT = CANCEL_GOT; @@ -77,7 +82,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_detach.c b/src/thread/pthread_detach.c index 77772af2..d73a500e 100644 --- a/src/thread/pthread_detach.c +++ b/src/thread/pthread_detach.c @@ -5,8 +5,12 @@ static int __pthread_detach(pthread_t t) { /* If the cas fails, detach state is either already-detached * or exiting/exited, and pthread_join will trap or cleanup. */ - if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) - return __pthread_join(t, 0); + if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) { + int cs; + __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + __pthread_join(t, 0); + __pthread_setcancelstate(cs, 0); + } return 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/sem_getvalue.c b/src/thread/sem_getvalue.c index d9d83071..c0b7762d 100644 --- a/src/thread/sem_getvalue.c +++ b/src/thread/sem_getvalue.c @@ -1,8 +1,9 @@ #include <semaphore.h> +#include <limits.h> int sem_getvalue(sem_t *restrict sem, int *restrict valp) { int val = sem->__val[0]; - *valp = val < 0 ? 0 : val; + *valp = val & SEM_VALUE_MAX; return 0; } diff --git a/src/thread/sem_post.c b/src/thread/sem_post.c index 31e3293d..5c2517f2 100644 --- a/src/thread/sem_post.c +++ b/src/thread/sem_post.c @@ -1,17 +1,21 @@ #include <semaphore.h> +#include <limits.h> #include "pthread_impl.h" int sem_post(sem_t *sem) { - int val, waiters, priv = sem->__val[2]; + int val, new, waiters, priv = sem->__val[2]; do { val = sem->__val[0]; waiters = sem->__val[1]; - if (val == SEM_VALUE_MAX) { + if ((val & SEM_VALUE_MAX) == SEM_VALUE_MAX) { errno = EOVERFLOW; return -1; } - } while (a_cas(sem->__val, val, val+1+(val<0)) != val); - if (val<0 || waiters) __wake(sem->__val, 1, priv); + new = val + 1; + if (waiters <= 1) + new &= ~0x80000000; + } while (a_cas(sem->__val, val, new) != val); + if (val<0) __wake(sem->__val, waiters>1 ? 1 : -1, priv); return 0; } diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index 58d3ebfe..aa67376c 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -1,4 +1,5 @@ #include <semaphore.h> +#include <limits.h> #include "pthread_impl.h" static void cleanup(void *p) @@ -13,14 +14,15 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) if (!sem_trywait(sem)) return 0; int spins = 100; - while (spins-- && sem->__val[0] <= 0 && !sem->__val[1]) a_spin(); + while (spins-- && !(sem->__val[0] & SEM_VALUE_MAX) && !sem->__val[1]) + a_spin(); while (sem_trywait(sem)) { - int r; + int r, priv = sem->__val[2]; a_inc(sem->__val+1); - a_cas(sem->__val, 0, -1); + a_cas(sem->__val, 0, 0x80000000); pthread_cleanup_push(cleanup, (void *)(sem->__val+1)); - r = __timedwait_cp(sem->__val, -1, CLOCK_REALTIME, at, sem->__val[2]); + r = __timedwait_cp(sem->__val, 0x80000000, CLOCK_REALTIME, at, priv); pthread_cleanup_pop(1); if (r) { errno = r; diff --git a/src/thread/sem_trywait.c b/src/thread/sem_trywait.c index 04edf46b..beb435da 100644 --- a/src/thread/sem_trywait.c +++ b/src/thread/sem_trywait.c @@ -1,12 +1,12 @@ #include <semaphore.h> +#include <limits.h> #include "pthread_impl.h" int sem_trywait(sem_t *sem) { int val; - while ((val=sem->__val[0]) > 0) { - int new = val-1-(val==1 && sem->__val[1]); - if (a_cas(sem->__val, val, new)==val) return 0; + while ((val=sem->__val[0]) & SEM_VALUE_MAX) { + if (a_cas(sem->__val, val, val-1)==val) return 0; } errno = EAGAIN; return -1; 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/__map_file.c b/src/time/__map_file.c index d3cefa82..c2b29fe8 100644 --- a/src/time/__map_file.c +++ b/src/time/__map_file.c @@ -2,15 +2,14 @@ #include <fcntl.h> #include <sys/stat.h> #include "syscall.h" -#include "kstat.h" const char unsigned *__map_file(const char *pathname, size_t *size) { - struct kstat st; + struct stat st; const unsigned char *map = MAP_FAILED; int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return 0; - if (!syscall(SYS_fstat, fd, &st)) { + if (!__fstat(fd, &st)) { map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); *size = st.st_size; } diff --git a/src/time/__tz.c b/src/time/__tz.c index 3e2fcdcb..c34b3eb7 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -293,22 +293,20 @@ static size_t scan_trans(long long t, int local, size_t *alt) n = (index-trans)>>scale; if (a == n-1) return -1; if (a == 0) { - x = zi_read32(trans + (a<<scale)); - if (scale == 3) x = x<<32 | zi_read32(trans + (a<<scale) + 4); + x = zi_read32(trans); + if (scale == 3) x = x<<32 | zi_read32(trans + 4); else x = (int32_t)x; - if (local) off = (int32_t)zi_read32(types + 6 * index[a-1]); + /* Find the lowest non-DST type, or 0 if none. */ + size_t j = 0; + for (size_t i=abbrevs-types; i; i-=6) { + if (!types[i-6+4]) j = i-6; + } + if (local) off = (int32_t)zi_read32(types + j); + /* If t is before first transition, use the above-found type + * and the index-zero (after transition) type as the alt. */ if (t - off < (int64_t)x) { - for (a=0; a<(abbrevs-types)/6; a++) { - if (types[6*a+4] != types[4]) break; - } - if (a == (abbrevs-types)/6) a = 0; - if (types[6*a+4]) { - *alt = a; - return 0; - } else { - *alt = 0; - return a; - } + if (alt) *alt = index[0]; + return j/6; } } diff --git a/src/time/clock_getcpuclockid.c b/src/time/clock_getcpuclockid.c index 8a0e2d4c..bce1e8ab 100644 --- a/src/time/clock_getcpuclockid.c +++ b/src/time/clock_getcpuclockid.c @@ -8,6 +8,7 @@ int clock_getcpuclockid(pid_t pid, clockid_t *clk) struct timespec ts; clockid_t id = (-pid-1)*8U + 2; int ret = __syscall(SYS_clock_getres, id, &ts); + if (ret == -EINVAL) ret = -ESRCH; if (ret) return -ret; *clk = id; return 0; diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index 3e1d0975..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; @@ -80,10 +83,12 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) return __syscall_ret(r); long ts32[2]; r = __syscall(SYS_clock_gettime, clk, ts32); +#ifdef SYS_gettimeofday if (r==-ENOSYS && clk==CLOCK_REALTIME) { r = __syscall(SYS_gettimeofday, ts32, 0); ts32[1] *= 1000; } +#endif if (!r) { ts->tv_sec = ts32[0]; ts->tv_nsec = ts32[1]; @@ -92,6 +97,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) return __syscall_ret(r); #else r = __syscall(SYS_clock_gettime, clk, ts); +#ifdef SYS_gettimeofday if (r == -ENOSYS) { if (clk == CLOCK_REALTIME) { __syscall(SYS_gettimeofday, ts, 0); @@ -100,6 +106,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) } r = -EINVAL; } +#endif return __syscall_ret(r); #endif } 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/nice.c b/src/unistd/nice.c index 6c25c8c3..1c2295ff 100644 --- a/src/unistd/nice.c +++ b/src/unistd/nice.c @@ -1,4 +1,5 @@ #include <unistd.h> +#include <errno.h> #include <sys/resource.h> #include <limits.h> #include "syscall.h" @@ -12,5 +13,11 @@ int nice(int inc) prio += getpriority(PRIO_PROCESS, 0); if (prio > NZERO-1) prio = NZERO-1; if (prio < -NZERO) prio = -NZERO; - return setpriority(PRIO_PROCESS, 0, prio) ? -1 : prio; + if (setpriority(PRIO_PROCESS, 0, prio)) { + if (errno == EACCES) + errno = EPERM; + return -1; + } else { + return prio; + } } 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); |