summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--VERSION2
-rw-r--r--WHATSNEW51
-rw-r--r--arch/riscv64/bits/signal.h4
-rw-r--r--arch/s390x/bits/alltypes.h.in4
-rw-r--r--arch/s390x/bits/float.h6
-rw-r--r--arch/sh/bits/signal.h13
-rw-r--r--arch/sh/pthread_arch.h4
-rw-r--r--include/stdlib.h1
-rw-r--r--src/aio/aio.c18
-rw-r--r--src/internal/locale_impl.h2
-rw-r--r--src/locale/freelocale.c5
-rw-r--r--src/locale/locale_map.c13
-rw-r--r--src/locale/newlocale.c32
-rw-r--r--src/locale/setlocale.c11
-rw-r--r--src/malloc/reallocarray.c13
-rw-r--r--src/misc/ioctl.c18
-rw-r--r--src/string/strstr.c2
-rw-r--r--src/thread/pthread_attr_get.c2
-rw-r--r--src/thread/s390x/clone.s6
-rw-r--r--src/thread/s390x/syscall_cp.s2
20 files changed, 157 insertions, 52 deletions
diff --git a/VERSION b/VERSION
index 6085e946..23aa8390 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.1
+1.2.2
diff --git a/WHATSNEW b/WHATSNEW
index d9826fc0..e1d01982 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -2236,3 +2236,54 @@ arch-specific bugs fixed:
- mips* had negated error codes for some syscalls (kernel bug)
- mips* SIGEMT was wrongly called SIGSTKFLT
- sh fesetround didn't work correctly on sh
+
+
+
+1.2.2 release notes
+
+major changes:
+- child restrictions lifted after fork of multithreaded parent
+
+new features:
+- _Fork function (POSIX-future)
+- reallocarray function (extension from OpenBSD, now widespread)
+- gettid function (kernel tid as supported concept)
+- SIGEV_THREAD_ID sigevent API (Linux extension)
+- tcgetwinsize and tcsetwinsize functions (POSIX-future)
+
+performance:
+- faster software sqrt on archs without native sqrt instruction
+
+compatibility:
+- realpath no longer depends on procfs availability & accuracy
+- time zone parser now always prefers 64-bit tables if present
+- crypt_blowfish now supports $2b$ prefix
+- res_query now reports errors via h_errno
+- set*id and setrlimit are now safe in vforked/cloned child
+- setgroups now applies to all threads
+- dlopen debugger notification is improved, should work with lldb
+- setrlimit no longer needs __synccall broadcast on linux 2.6.36+
+- faccessat with AT_EACCESS no longer needs child process on linux 5.8+
+
+bugs fixed:
+- buffer overflow and infinite loop errors in wcsnrtombs (CVE-2020-28928)
+- sem_close unmapped still-referenced semaphores
+- fork of process with active aio could deadlock or crash paren
+- pthread_cond_wait was broken with priority-inheritance mutex
+- getgrouplist wrongly failed when nscd reported an empty list
+- abort could leak modified SIGABRT disposition to fork or posix_spawn child
+- regression with mallocng: malloc_usable_size(0) crashed
+- readlink wrongly gave EINVAL on zero length dest buffer
+- sqrtl was severely inaccurate (not correctly rounded) on ldquad archs
+- assert failure wrongly flushed stdio (possible deadlock)
+- MUSL_LOCPATH search was broken with multiple components
+- missing newline in herror output
+- possible deadlock in pthread_exit with pshared mutex or barrier usage
+- pthread_mutexattr_getprotocol didn't read back protocol
+- v4l2 ioctl translation for pre-time64 kernels didn't work
+
+arch-specific bugs fixed:
+- x86_64 longjmp failed to handle 0 argument reliably
+- 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
diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
index b006334f..287367db 100644
--- a/arch/riscv64/bits/signal.h
+++ b/arch/riscv64/bits/signal.h
@@ -60,10 +60,10 @@ struct sigaltstack {
size_t ss_size;
};
-typedef struct ucontext_t
+typedef struct __ucontext
{
unsigned long uc_flags;
- struct ucontext_t *uc_link;
+ struct __ucontext *uc_link;
stack_t uc_stack;
sigset_t uc_sigmask;
mcontext_t uc_mcontext;
diff --git a/arch/s390x/bits/alltypes.h.in b/arch/s390x/bits/alltypes.h.in
index 15d18c8f..6c0eb7f4 100644
--- a/arch/s390x/bits/alltypes.h.in
+++ b/arch/s390x/bits/alltypes.h.in
@@ -9,7 +9,11 @@
TYPEDEF int wchar_t;
#endif
+#if defined(__FLT_EVAL_METHOD__) && __FLT_EVAL_METHOD__ == 1
TYPEDEF double float_t;
+#else
+TYPEDEF float float_t;
+#endif
TYPEDEF double double_t;
TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
diff --git a/arch/s390x/bits/float.h b/arch/s390x/bits/float.h
index 90b73bee..e188cb61 100644
--- a/arch/s390x/bits/float.h
+++ b/arch/s390x/bits/float.h
@@ -1,4 +1,8 @@
-#define FLT_EVAL_METHOD 1
+#ifdef __FLT_EVAL_METHOD__
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#else
+#define FLT_EVAL_METHOD 0
+#endif
#define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L
#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
diff --git a/arch/sh/bits/signal.h b/arch/sh/bits/signal.h
index 160311fa..d0b14828 100644
--- a/arch/sh/bits/signal.h
+++ b/arch/sh/bits/signal.h
@@ -9,7 +9,16 @@
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
typedef int greg_t, gregset_t[16];
typedef int freg_t, fpregset_t[16];
-typedef struct sigcontext {
+typedef struct {
+ unsigned long oldmask;
+ unsigned long gregs[16];
+ unsigned long pc, pr, sr;
+ unsigned long gbr, mach, macl;
+ unsigned long fpregs[16];
+ unsigned long xfpregs[16];
+ unsigned int fpscr, fpul, ownedfp;
+} mcontext_t;
+struct sigcontext {
unsigned long oldmask;
unsigned long sc_regs[16];
unsigned long sc_pc, sc_pr, sc_sr;
@@ -17,7 +26,7 @@ typedef struct sigcontext {
unsigned long sc_fpregs[16];
unsigned long sc_xfpregs[16];
unsigned int sc_fpscr, sc_fpul, sc_ownedfp;
-} mcontext_t;
+};
#else
typedef struct {
unsigned long __regs[58];
diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h
index 0fcf70d2..199c2d55 100644
--- a/arch/sh/pthread_arch.h
+++ b/arch/sh/pthread_arch.h
@@ -8,9 +8,9 @@ static inline uintptr_t __get_tp()
#define TLS_ABOVE_TP
#define GAP_ABOVE_TP 8
-#define MC_PC sc_pc
+#define MC_PC pc
#ifdef __FDPIC__
-#define MC_GOT sc_regs[12]
+#define MC_GOT gregs[12]
#define CANCEL_GOT (*(uintptr_t *)((char *)__syscall_cp_asm+sizeof(uintptr_t)))
#endif
diff --git a/include/stdlib.h b/include/stdlib.h
index 194c2033..b54a051f 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -145,6 +145,7 @@ int getloadavg(double *, int);
int clearenv(void);
#define WCOREDUMP(s) ((s) & 0x80)
#define WIFCONTINUED(s) ((s) == 0xffff)
+void *reallocarray (void *, size_t, size_t);
#endif
#ifdef _GNU_SOURCE
diff --git a/src/aio/aio.c b/src/aio/aio.c
index e004f98b..a1a3e791 100644
--- a/src/aio/aio.c
+++ b/src/aio/aio.c
@@ -76,6 +76,10 @@ static struct aio_queue *****map;
static volatile int aio_fd_cnt;
volatile int __aio_fut;
+static size_t io_thread_stack_size;
+
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+
static struct aio_queue *__aio_get_queue(int fd, int need)
{
if (fd < 0) {
@@ -90,6 +94,10 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
pthread_rwlock_unlock(&maplock);
if (fcntl(fd, F_GETFD) < 0) return 0;
pthread_rwlock_wrlock(&maplock);
+ if (!io_thread_stack_size) {
+ unsigned long val = __getauxval(AT_MINSIGSTKSZ);
+ io_thread_stack_size = MAX(MINSIGSTKSZ+2048, val+512);
+ }
if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24);
if (!map) goto out;
if (!map[a]) map[a] = calloc(sizeof **map, 256);
@@ -265,15 +273,6 @@ static void *io_thread_func(void *ctx)
return 0;
}
-static size_t io_thread_stack_size = MINSIGSTKSZ+2048;
-static pthread_once_t init_stack_size_once;
-
-static void init_stack_size()
-{
- unsigned long val = __getauxval(AT_MINSIGSTKSZ);
- if (val > MINSIGSTKSZ) io_thread_stack_size = val + 512;
-}
-
static int submit(struct aiocb *cb, int op)
{
int ret = 0;
@@ -299,7 +298,6 @@ static int submit(struct aiocb *cb, int op)
else
pthread_attr_init(&a);
} else {
- pthread_once(&init_stack_size_once, init_stack_size);
pthread_attr_init(&a);
pthread_attr_setstacksize(&a, io_thread_stack_size);
pthread_attr_setguardsize(&a, 0);
diff --git a/src/internal/locale_impl.h b/src/internal/locale_impl.h
index 741a71c4..4431a92e 100644
--- a/src/internal/locale_impl.h
+++ b/src/internal/locale_impl.h
@@ -15,6 +15,8 @@ struct __locale_map {
const struct __locale_map *next;
};
+extern hidden volatile int __locale_lock[1];
+
extern hidden const struct __locale_map __c_dot_utf8;
extern hidden const struct __locale_struct __c_locale;
extern hidden const struct __locale_struct __c_dot_utf8_locale;
diff --git a/src/locale/freelocale.c b/src/locale/freelocale.c
index 802b8bfe..385d1206 100644
--- a/src/locale/freelocale.c
+++ b/src/locale/freelocale.c
@@ -1,6 +1,11 @@
#include <stdlib.h>
#include "locale_impl.h"
+#define malloc undef
+#define calloc undef
+#define realloc undef
+#define free __libc_free
+
void freelocale(locale_t l)
{
if (__loc_is_allocated(l)) free(l);
diff --git a/src/locale/locale_map.c b/src/locale/locale_map.c
index fa51f2e3..da61f7fc 100644
--- a/src/locale/locale_map.c
+++ b/src/locale/locale_map.c
@@ -28,8 +28,8 @@ static const char envvars[][12] = {
"LC_MESSAGES",
};
-static volatile int lock[1];
-volatile int *const __locale_lockptr = lock;
+volatile int __locale_lock[1];
+volatile int *const __locale_lockptr = __locale_lock;
const struct __locale_map *__get_locale(int cat, const char *val)
{
@@ -63,14 +63,6 @@ const struct __locale_map *__get_locale(int cat, const char *val)
for (p=loc_head; p; p=p->next)
if (!strcmp(val, p->name)) return p;
- LOCK(lock);
-
- for (p=loc_head; p; p=p->next)
- if (!strcmp(val, p->name)) {
- UNLOCK(lock);
- return p;
- }
-
if (!libc.secure) path = getenv("MUSL_LOCPATH");
/* FIXME: add a default path? */
@@ -117,6 +109,5 @@ const struct __locale_map *__get_locale(int cat, const char *val)
* requested name was "C" or "POSIX". */
if (!new && cat == LC_CTYPE) new = (void *)&__c_dot_utf8;
- UNLOCK(lock);
return new;
}
diff --git a/src/locale/newlocale.c b/src/locale/newlocale.c
index d20a8489..9ac3cd38 100644
--- a/src/locale/newlocale.c
+++ b/src/locale/newlocale.c
@@ -2,16 +2,15 @@
#include <string.h>
#include <pthread.h>
#include "locale_impl.h"
+#include "lock.h"
-static pthread_once_t default_locale_once;
-static struct __locale_struct default_locale, default_ctype_locale;
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
-static void default_locale_init(void)
-{
- for (int i=0; i<LC_ALL; i++)
- default_locale.cat[i] = __get_locale(i, "");
- default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
-}
+static int default_locale_init_done;
+static struct __locale_struct default_locale, default_ctype_locale;
int __loc_is_allocated(locale_t loc)
{
@@ -19,7 +18,7 @@ int __loc_is_allocated(locale_t loc)
&& loc != &default_locale && loc != &default_ctype_locale;
}
-locale_t __newlocale(int mask, const char *name, locale_t loc)
+static locale_t do_newlocale(int mask, const char *name, locale_t loc)
{
struct __locale_struct tmp;
@@ -44,7 +43,12 @@ locale_t __newlocale(int mask, const char *name, locale_t loc)
/* And provide builtins for the initial default locale, and a
* variant of the C locale honoring the default locale's encoding. */
- pthread_once(&default_locale_once, default_locale_init);
+ if (!default_locale_init_done) {
+ for (int i=0; i<LC_ALL; i++)
+ default_locale.cat[i] = __get_locale(i, "");
+ default_ctype_locale.cat[LC_CTYPE] = default_locale.cat[LC_CTYPE];
+ default_locale_init_done = 1;
+ }
if (!memcmp(&tmp, &default_locale, sizeof tmp)) return &default_locale;
if (!memcmp(&tmp, &default_ctype_locale, sizeof tmp))
return &default_ctype_locale;
@@ -55,4 +59,12 @@ locale_t __newlocale(int mask, const char *name, locale_t loc)
return loc;
}
+locale_t __newlocale(int mask, const char *name, locale_t loc)
+{
+ LOCK(__locale_lock);
+ loc = do_newlocale(mask, name, loc);
+ UNLOCK(__locale_lock);
+ return loc;
+}
+
weak_alias(__newlocale, newlocale);
diff --git a/src/locale/setlocale.c b/src/locale/setlocale.c
index 2bc7b500..360c4437 100644
--- a/src/locale/setlocale.c
+++ b/src/locale/setlocale.c
@@ -9,12 +9,11 @@ static char buf[LC_ALL*(LOCALE_NAME_MAX+1)];
char *setlocale(int cat, const char *name)
{
- static volatile int lock[1];
const struct __locale_map *lm;
if ((unsigned)cat > LC_ALL) return 0;
- LOCK(lock);
+ LOCK(__locale_lock);
/* For LC_ALL, setlocale is required to return a string which
* encodes the current setting for all categories. The format of
@@ -36,7 +35,7 @@ char *setlocale(int cat, const char *name)
}
lm = __get_locale(i, part);
if (lm == LOC_MAP_FAILED) {
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return 0;
}
tmp_locale.cat[i] = lm;
@@ -57,14 +56,14 @@ char *setlocale(int cat, const char *name)
s += l+1;
}
*--s = 0;
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return same==LC_ALL ? (char *)part : buf;
}
if (name) {
lm = __get_locale(cat, name);
if (lm == LOC_MAP_FAILED) {
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return 0;
}
libc.global_locale.cat[cat] = lm;
@@ -73,7 +72,7 @@ char *setlocale(int cat, const char *name)
}
char *ret = lm ? (char *)lm->name : "C";
- UNLOCK(lock);
+ UNLOCK(__locale_lock);
return ret;
}
diff --git a/src/malloc/reallocarray.c b/src/malloc/reallocarray.c
new file mode 100644
index 00000000..4a6ebe46
--- /dev/null
+++ b/src/malloc/reallocarray.c
@@ -0,0 +1,13 @@
+#define _BSD_SOURCE
+#include <errno.h>
+#include <stdlib.h>
+
+void *reallocarray(void *ptr, size_t m, size_t n)
+{
+ if (n && m > -1 / n) {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ return realloc(ptr, m * n);
+}
diff --git a/src/misc/ioctl.c b/src/misc/ioctl.c
index 89477511..49282811 100644
--- a/src/misc/ioctl.c
+++ b/src/misc/ioctl.c
@@ -4,6 +4,7 @@
#include <time.h>
#include <sys/time.h>
#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#include "syscall.h"
@@ -28,6 +29,12 @@ struct ioctl_compat_map {
* number producing macros; only size of result is meaningful. */
#define new_misaligned(n) struct { int i; time_t t; char c[(n)-4]; }
+struct v4l2_event {
+ uint32_t a;
+ uint64_t b[8];
+ uint32_t c[2], ts[2], d[9];
+};
+
static const struct ioctl_compat_map compat_map[] = {
{ SIOCGSTAMP, SIOCGSTAMP_OLD, 8, R, 0, OFFS(0, 4) },
{ SIOCGSTAMPNS, SIOCGSTAMPNS_OLD, 8, R, 0, OFFS(0, 4) },
@@ -49,13 +56,14 @@ static const struct ioctl_compat_map compat_map[] = {
{ 0, 0, 8, WR, 1, OFFS(0,4) }, /* snd_pcm_mmap_control */
/* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */
- { _IOWR('V', 9, new_misaligned(72)), _IOWR('V', 9, char[72]), 72, WR, 0, OFFS(20) },
- { _IOWR('V', 15, new_misaligned(72)), _IOWR('V', 15, char[72]), 72, WR, 0, OFFS(20) },
- { _IOWR('V', 17, new_misaligned(72)), _IOWR('V', 17, char[72]), 72, WR, 0, OFFS(20) },
- { _IOWR('V', 93, new_misaligned(72)), _IOWR('V', 93, char[72]), 72, WR, 0, OFFS(20) },
+ { _IOWR('V', 9, new_misaligned(68)), _IOWR('V', 9, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 15, new_misaligned(68)), _IOWR('V', 15, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 17, new_misaligned(68)), _IOWR('V', 17, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 93, new_misaligned(68)), _IOWR('V', 93, char[68]), 68, WR, 1, OFFS(20, 24) },
/* VIDIOC_DQEVENT */
- { _IOR('V', 89, new_misaligned(96)), _IOR('V', 89, char[96]), 96, R, 0, OFFS(76,80) },
+ { _IOR('V', 89, new_misaligned(120)), _IOR('V', 89, struct v4l2_event), sizeof(struct v4l2_event),
+ R, 0, OFFS(offsetof(struct v4l2_event, ts[0]), offsetof(struct v4l2_event, ts[1])) },
/* VIDIOC_OMAP3ISP_STAT_REQ */
{ _IOWR('V', 192+6, char[32]), _IOWR('V', 192+6, char[24]), 22, WR, 0, OFFS(0,4) },
diff --git a/src/string/strstr.c b/src/string/strstr.c
index 43a0207a..96657bc2 100644
--- a/src/string/strstr.c
+++ b/src/string/strstr.c
@@ -96,7 +96,7 @@ static char *twoway_strstr(const unsigned char *h, const unsigned char *n)
for (;;) {
/* Update incremental end-of-haystack pointer */
if (z-h < l) {
- /* Fast estimate for MIN(l,63) */
+ /* Fast estimate for MAX(l,63) */
size_t grow = l | 63;
const unsigned char *z2 = memchr(z, 0, grow);
if (z2) {
diff --git a/src/thread/pthread_attr_get.c b/src/thread/pthread_attr_get.c
index 4aa5afdb..f12ff442 100644
--- a/src/thread/pthread_attr_get.c
+++ b/src/thread/pthread_attr_get.c
@@ -70,7 +70,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restr
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict protocol)
{
- *protocol = PTHREAD_PRIO_NONE;
+ *protocol = a->__attr / 8U % 2;
return 0;
}
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared)
diff --git a/src/thread/s390x/clone.s b/src/thread/s390x/clone.s
index 577748ea..2125f20b 100644
--- a/src/thread/s390x/clone.s
+++ b/src/thread/s390x/clone.s
@@ -17,6 +17,9 @@ __clone:
# if (!tid) syscall(SYS_exit, a(d));
# return tid;
+ # preserve call-saved register used as syscall arg
+ stg %r6, 48(%r15)
+
# create initial stack frame for new thread
nill %r3, 0xfff8
aghi %r3, -160
@@ -35,6 +38,9 @@ __clone:
lg %r6, 160(%r15)
svc 120
+ # restore call-saved register
+ lg %r6, 48(%r15)
+
# if error or if we're the parent, return
ltgr %r2, %r2
bnzr %r14
diff --git a/src/thread/s390x/syscall_cp.s b/src/thread/s390x/syscall_cp.s
index c1da40de..d094cbf5 100644
--- a/src/thread/s390x/syscall_cp.s
+++ b/src/thread/s390x/syscall_cp.s
@@ -14,6 +14,7 @@ __cp_begin:
icm %r2, 15, 0(%r2)
jne __cp_cancel
+ stg %r6, 48(%r15)
stg %r7, 56(%r15)
lgr %r1, %r3
lgr %r2, %r4
@@ -26,6 +27,7 @@ __cp_begin:
__cp_end:
lg %r7, 56(%r15)
+ lg %r6, 48(%r15)
br %r14
__cp_cancel: