aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2022-09-28 23:39:44 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2022-09-28 23:39:44 +0000
commit31c683ba8b6ad55fcd707c65ebc6e842d6c01aae (patch)
tree0767d494f3b4b6f5b9d3e6ba2dd93f8f2c6543ef
parentf3fb4448935e650667c054d7350898c81065f3c1 (diff)
parentaa450e62f093f7e9936932415386cd4ba832891e (diff)
downloadmusl-31c683ba8b6ad55fcd707c65ebc6e842d6c01aae.tar.gz
Merge remote-tracking branch 'aosp/upstream-master' into update am: aa450e62f0
Original change: https://android-review.googlesource.com/c/platform/external/musl/+/2228150 Change-Id: I511d784a9ae3a4e1b6bfe55a35af38d2235fc54a Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--arch/arm/syscall_arch.h7
-rwxr-xr-xconfigure5
-rw-r--r--include/elf.h8
-rw-r--r--include/strings.h1
-rw-r--r--include/unistd.h4
-rw-r--r--ldso/dlstart.c15
-rw-r--r--ldso/dynlink.c53
-rw-r--r--sources.bp2
-rw-r--r--src/conf/confstr.c2
-rw-r--r--src/conf/sysconf.c13
-rw-r--r--src/include/sys/stat.h9
-rw-r--r--src/internal/dynlink.h2
-rw-r--r--src/internal/syscall.h26
-rw-r--r--src/linux/epoll.c1
-rw-r--r--src/linux/membarrier.c2
-rw-r--r--src/misc/getrlimit.c6
-rw-r--r--src/misc/mntent.c12
-rw-r--r--src/misc/setrlimit.c6
-rw-r--r--src/network/getaddrinfo.c2
-rw-r--r--src/network/gethostbyaddr_r.c5
-rw-r--r--src/network/gethostbyname2_r.c3
-rw-r--r--src/network/lookup_name.c5
-rw-r--r--src/network/netlink.h2
-rw-r--r--src/network/res_mkquery.c1
-rw-r--r--src/network/res_msend.c8
-rw-r--r--src/process/aarch64/vfork.s9
-rw-r--r--src/stat/fchmodat.c15
-rw-r--r--src/stat/fstat.c6
-rw-r--r--src/stat/fstatat.c14
-rw-r--r--src/stdio/freopen.c2
-rw-r--r--src/stdio/open_wmemstream.c6
-rw-r--r--src/stdio/tempnam.c8
-rw-r--r--src/stdio/tmpnam.c8
-rw-r--r--src/stdlib/qsort_nr.c2
-rw-r--r--src/temp/__randname.c3
-rw-r--r--src/thread/pthread_cancel.c2
-rw-r--r--src/thread/synccall.c2
-rw-r--r--src/time/__map_file.c5
-rw-r--r--src/time/clock_getcpuclockid.c1
-rw-r--r--src/time/clock_gettime.c7
-rw-r--r--src/time/timer_create.c6
41 files changed, 220 insertions, 76 deletions
diff --git a/arch/arm/syscall_arch.h b/arch/arm/syscall_arch.h
index a877b2cf..624e992e 100644
--- a/arch/arm/syscall_arch.h
+++ b/arch/arm/syscall_arch.h
@@ -101,3 +101,10 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
#define SYSCALL_FADVISE_6_ARG
#define SYSCALL_IPC_BROKEN_MODE
+
+#define VDSO_USEFUL
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
+#define VDSO_CGT_VER "LINUX_2.6"
+#define VDSO_CGT_WORKAROUND 1
diff --git a/configure b/configure
index ca5cbc0b..6f5453f5 100755
--- a/configure
+++ b/configure
@@ -723,11 +723,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/elf.h b/include/elf.h
index 86e2f0bb..9e980a29 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
@@ -754,7 +755,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/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/unistd.h b/include/unistd.h
index 212263a7..0e8149e4 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -425,6 +425,8 @@ pid_t gettid(void);
#define _SC_XOPEN_STREAMS 246
#define _SC_THREAD_ROBUST_PRIO_INHERIT 247
#define _SC_THREAD_ROBUST_PRIO_PROTECT 248
+#define _SC_MINSIGSTKSZ 249
+#define _SC_SIGSTKSZ 250
#define _CS_PATH 0
#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1
@@ -467,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/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 853f6e91..24fe47cf 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -32,7 +32,9 @@
#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))
@@ -212,7 +214,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];
}
}
@@ -517,6 +520,23 @@ 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)
+{
+ 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;
@@ -870,7 +890,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;
}
@@ -1359,13 +1379,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;
@@ -1762,6 +1786,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. */
@@ -2357,7 +2384,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);
@@ -2371,3 +2398,7 @@ static void error(const char *fmt, ...)
__dl_vseterr(fmt, ap);
va_end(ap);
}
+
+static void error_noop(const char *fmt, ...)
+{
+}
diff --git a/sources.bp b/sources.bp
index 0e63694b..30e10321 100644
--- a/sources.bp
+++ b/sources.bp
@@ -1353,6 +1353,7 @@ cc_defaults {
"src/math/aarch64/sqrtf.c",
"src/math/aarch64/trunc.c",
"src/math/aarch64/truncf.c",
+ "src/process/aarch64/vfork.s",
"src/setjmp/aarch64/longjmp.s",
"src/setjmp/aarch64/setjmp.s",
"src/signal/aarch64/restore.s",
@@ -1395,6 +1396,7 @@ cc_defaults {
"src/math/sqrtf.c",
"src/math/trunc.c",
"src/math/truncf.c",
+ "src/process/vfork.c",
"src/setjmp/longjmp.c",
"src/setjmp/setjmp.c",
"src/signal/restore.c",
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/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..830354eb 100644
--- a/src/internal/dynlink.h
+++ b/src/internal/dynlink.h
@@ -93,7 +93,7 @@ struct fdpic_dummy_loadmap {
#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/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/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/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/misc/getrlimit.c b/src/misc/getrlimit.c
index 2ab2f0f4..bf676307 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,9 @@ 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/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/setrlimit.c b/src/misc/setrlimit.c
index 8340aee0..5b713cf3 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,9 @@ 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/network/getaddrinfo.c b/src/network/getaddrinfo.c
index efaab306..9df045f6 100644
--- a/src/network/getaddrinfo.c
+++ b/src/network/getaddrinfo.c
@@ -66,9 +66,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:
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_r.c b/src/network/gethostbyname2_r.c
index fc894877..c9f3acc4 100644
--- a/src/network/gethostbyname2_r.c
+++ b/src/network/gethostbyname2_r.c
@@ -22,7 +22,7 @@ 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_AGAIN:
*err = TRY_AGAIN;
return EAGAIN;
@@ -30,7 +30,6 @@ int gethostbyname2_r(const char *name, int af,
case EAI_FAIL:
*err = NO_RECOVERY;
return EBADMSG;
- case EAI_MEMORY:
case EAI_SYSTEM:
*err = NO_RECOVERY;
return errno;
diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c
index aa558c19..bec6ba22 100644
--- a/src/network/lookup_name.c
+++ b/src/network/lookup_name.c
@@ -153,8 +153,11 @@ 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;
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++;
}
}
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..9adaea13 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -68,14 +68,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);
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/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..27db0ccb 100644
--- a/src/stat/fstat.c
+++ b/src/stat/fstat.c
@@ -4,12 +4,14 @@
#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);
}
+weak_alias(__fstat, fstat);
+
#if !_REDIR_TIME64
weak_alias(fstat, fstat64);
#endif
diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
index de165b5c..74c51cf5 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,25 @@ 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);
}
+weak_alias(__fstatat, fstatat);
+
#if !_REDIR_TIME64
weak_alias(fstatat, fstatat64);
#endif
diff --git a/src/stdio/freopen.c b/src/stdio/freopen.c
index 615d4b47..96bfbb42 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;
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/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/stdlib/qsort_nr.c b/src/stdlib/qsort_nr.c
index efe7ccec..8ffe71d0 100644
--- a/src/stdlib/qsort_nr.c
+++ b/src/stdlib/qsort_nr.c
@@ -10,5 +10,5 @@ static int wrapper_cmp(const void *v1, const void *v2, void *cmp)
void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
{
- __qsort_r(base, nel, width, wrapper_cmp, cmp);
+ __qsort_r(base, nel, width, wrapper_cmp, (void *)cmp);
}
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/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
index 2f9d5e97..2d3a98ea 100644
--- a/src/thread/pthread_cancel.c
+++ b/src/thread/pthread_cancel.c
@@ -77,7 +77,7 @@ void __testcancel()
static void init_cancellation()
{
struct sigaction sa = {
- .sa_flags = SA_SIGINFO | SA_RESTART,
+ .sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK,
.sa_sigaction = cancel_handler
};
memset(&sa.sa_mask, -1, _NSIG/8);
diff --git a/src/thread/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/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;