Commit 56101f21 authored by Timo Teräs's avatar Timo Teräs Committed by Natanael Copa

main/musl: cherry-pick upstream fixes and improvements

fixes #4621
fixes #4949

(cherry picked from commit 8a4ccf53)
parent d692ac08
From b114190b29417fff6f701eea3a3b3b6030338280 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Sat, 24 Oct 2015 22:42:10 -0400
Subject: fix single-byte overflow of malloc'd buffer in getdelim
Subject: [PATCH] fix single-byte overflow of malloc'd buffer in getdelim
the buffer enlargement logic here accounted for the terminating null
byte, but not for the possibility of hitting the delimiter in the
......@@ -28,5 +28,5 @@ index a88c393..3077490 100644
*n = i+k+2;
if (*n < SIZE_MAX/4) *n *= 2;
--
cgit v0.11.2
2.7.0
From 2683e267fa6c20d2e7a498a85f79a1dfc4301f23 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Mon, 26 Oct 2015 18:42:22 -0400
Subject: [PATCH] safely handle failure to open hosts, services, resolv.conf
files
previously, transient failures like fd exhaustion or other
resource-related errors were treated the same as non-existence of
these files, leading to fallbacks or false-negative results. in
particular:
- failure to open hosts resulted in fallback to dns, possibly yielding
EAI_NONAME for a hostname that should be defined locally, or an
unwanted result from dns that the hosts file was intended to
replace.
- failure to open services resulted in EAI_SERVICE.
- failure to open resolv.conf resulted in querying localhost rather
than the configured nameservers.
now, only permanent errors trigger the fallback behaviors above; all
other errors are reportable to the caller as EAI_SYSTEM.
---
src/network/lookup_name.c | 10 +++++++++-
src/network/lookup_serv.c | 10 +++++++++-
src/network/res_msend.c | 13 +++++++++++--
3 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c
index 0225a93..df9e623 100644
--- a/src/network/lookup_name.c
+++ b/src/network/lookup_name.c
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
+#include <errno.h>
#include "lookup.h"
#include "stdio_impl.h"
#include "syscall.h"
@@ -51,7 +52,14 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
int cnt = 0;
unsigned char _buf[1032];
FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
- if (!f) return 0;
+ if (!f) switch (errno) {
+ case ENOENT:
+ case ENOTDIR:
+ case EACCES:
+ return 0;
+ default:
+ return EAI_SYSTEM;
+ }
while (fgets(line, sizeof line, f) && cnt < MAXADDRS) {
char *p, *z;
diff --git a/src/network/lookup_serv.c b/src/network/lookup_serv.c
index 4faa5bc..66ebaea 100644
--- a/src/network/lookup_serv.c
+++ b/src/network/lookup_serv.c
@@ -4,6 +4,7 @@
#include <ctype.h>
#include <string.h>
#include <fcntl.h>
+#include <errno.h>
#include "lookup.h"
#include "stdio_impl.h"
@@ -69,7 +70,14 @@ int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int pro
unsigned char _buf[1032];
FILE _f, *f = __fopen_rb_ca("/etc/services", &_f, _buf, sizeof _buf);
- if (!f) return EAI_SERVICE;
+ if (!f) switch (errno) {
+ case ENOENT:
+ case ENOTDIR:
+ case EACCES:
+ return EAI_SERVICE;
+ default:
+ return EAI_SYSTEM;
+ }
while (fgets(line, sizeof line, f) && cnt < MAXSERVS) {
if ((p=strchr(line, '#'))) *p++='\n', *p=0;
diff --git a/src/network/res_msend.c b/src/network/res_msend.c
index 35f106d..d0e8e48 100644
--- a/src/network/res_msend.c
+++ b/src/network/res_msend.c
@@ -54,7 +54,15 @@ int __res_msend(int nqueries, const unsigned char *const *queries,
/* Get nameservers from resolv.conf, fallback to localhost */
f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf);
- if (f) for (nns=0; nns<3 && fgets(line, sizeof line, f); ) {
+ if (!f) switch (errno) {
+ case ENOENT:
+ case ENOTDIR:
+ case EACCES:
+ goto no_resolv_conf;
+ default:
+ return -1;
+ }
+ for (nns=0; nns<3 && fgets(line, sizeof line, f); ) {
if (!strncmp(line, "options", 7) && isspace(line[7])) {
unsigned long x;
char *p, *z;
@@ -92,7 +100,8 @@ int __res_msend(int nqueries, const unsigned char *const *queries,
}
}
}
- if (f) __fclose_ca(f);
+ __fclose_ca(f);
+no_resolv_conf:
if (!nns) {
ns[0].sin.sin_family = AF_INET;
ns[0].sin.sin_port = htons(53);
--
2.7.0
From 6eada2edb302ff061be8546b23c9cb836621d122 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 26 Oct 2015 23:03:55 +0100
Subject: [PATCH] getnameinfo: make size check not fail for bigger sizes
getnameinfo() compares the size of the given struct sockaddr with
sizeof(struct sockaddr_in) and sizeof(struct sockaddr_in6) depending on
the net family. When you add a sockaddr of size sizeof(struct
sockaddr_storage) this function will fail because the size of the
sockaddr is too big. Change the check that it only fails if the size is
too small, but make it work when it is too big for example when someone
calls this function with a struct sockaddr_storage and its size.
This fixes a problem with IoTivity 1.0.0 and musl.
glibc and bionic are only failing if it is smaller, net/freebsd
implemented the != check.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
src/network/getnameinfo.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c
index 3484fc6..5e6fae3 100644
--- a/src/network/getnameinfo.c
+++ b/src/network/getnameinfo.c
@@ -135,13 +135,13 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
switch (af) {
case AF_INET:
a = (void *)&((struct sockaddr_in *)sa)->sin_addr;
- if (sl != sizeof(struct sockaddr_in)) return EAI_FAMILY;
+ if (sl < sizeof(struct sockaddr_in)) return EAI_FAMILY;
mkptr4(ptr, a);
scopeid = 0;
break;
case AF_INET6:
a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr;
- if (sl != sizeof(struct sockaddr_in6)) return EAI_FAMILY;
+ if (sl < sizeof(struct sockaddr_in6)) return EAI_FAMILY;
if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12))
mkptr6(ptr, a);
else
--
2.7.0
From cb1bf2f321b45a06447133b3db00621b7300c456 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Mon, 2 Nov 2015 12:39:28 -0500
Subject: [PATCH] properly access mcontext_t program counter in cancellation
handler
using the actual mcontext_t definition rather than an overlaid pointer
array both improves correctness/readability and eliminates some ugly
hacks for archs with 64-bit registers bit 32-bit program counter.
also fix UB due to comparison of pointers not in a common array
object.
---
arch/aarch64/pthread_arch.h | 2 +-
arch/arm/pthread_arch.h | 2 +-
arch/i386/pthread_arch.h | 2 +-
arch/microblaze/pthread_arch.h | 2 +-
arch/mips/pthread_arch.h | 2 +-
arch/or1k/pthread_arch.h | 3 +--
arch/powerpc/pthread_arch.h | 3 +--
arch/sh/pthread_arch.h | 2 +-
arch/x32/pthread_arch.h | 2 +-
arch/x86_64/pthread_arch.h | 2 +-
src/thread/pthread_cancel.c | 7 ++++---
11 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/arch/aarch64/pthread_arch.h b/arch/aarch64/pthread_arch.h
index 74276f4..b2e2d8f 100644
--- a/arch/aarch64/pthread_arch.h
+++ b/arch/aarch64/pthread_arch.h
@@ -8,4 +8,4 @@ static inline struct pthread *__pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 16)
-#define CANCEL_REG_IP 33
+#define MC_PC pc
diff --git a/arch/arm/pthread_arch.h b/arch/arm/pthread_arch.h
index 4a4dd09..8b8a7fb 100644
--- a/arch/arm/pthread_arch.h
+++ b/arch/arm/pthread_arch.h
@@ -27,4 +27,4 @@ static inline pthread_t __pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
-#define CANCEL_REG_IP 18
+#define MC_PC arm_pc
diff --git a/arch/i386/pthread_arch.h b/arch/i386/pthread_arch.h
index 1c06c76..7f38a56 100644
--- a/arch/i386/pthread_arch.h
+++ b/arch/i386/pthread_arch.h
@@ -7,4 +7,4 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 14
+#define MC_PC gregs[REG_EIP]
diff --git a/arch/microblaze/pthread_arch.h b/arch/microblaze/pthread_arch.h
index 259d3d6..08d1ba7 100644
--- a/arch/microblaze/pthread_arch.h
+++ b/arch/microblaze/pthread_arch.h
@@ -7,4 +7,4 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 32
+#define MC_PC regs.pc
diff --git a/arch/mips/pthread_arch.h b/arch/mips/pthread_arch.h
index 93edbd4..8a49965 100644
--- a/arch/mips/pthread_arch.h
+++ b/arch/mips/pthread_arch.h
@@ -16,4 +16,4 @@ static inline struct pthread *__pthread_self()
#define DTP_OFFSET 0x8000
-#define CANCEL_REG_IP (3-(union {int __i; char __b;}){1}.__b)
+#define MC_PC pc
diff --git a/arch/or1k/pthread_arch.h b/arch/or1k/pthread_arch.h
index ad63169..7decd76 100644
--- a/arch/or1k/pthread_arch.h
+++ b/arch/or1k/pthread_arch.h
@@ -14,5 +14,4 @@ static inline struct pthread *__pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread))
-/* word-offset to 'pc' in mcontext_t */
-#define CANCEL_REG_IP 32
+#define MC_PC regs.pc
diff --git a/arch/powerpc/pthread_arch.h b/arch/powerpc/pthread_arch.h
index bb7405d..7c5c4fa 100644
--- a/arch/powerpc/pthread_arch.h
+++ b/arch/powerpc/pthread_arch.h
@@ -15,9 +15,8 @@ static inline struct pthread *__pthread_self()
#define DTP_OFFSET 0x8000
-// offset of the PC register in mcontext_t, divided by the system wordsize
// the kernel calls the ip "nip", it's the first saved value after the 32
// GPRs.
-#define CANCEL_REG_IP 32
+#define MC_PC gregs[32]
#define CANARY canary_at_end
diff --git a/arch/sh/pthread_arch.h b/arch/sh/pthread_arch.h
index 65c389f..2756e7e 100644
--- a/arch/sh/pthread_arch.h
+++ b/arch/sh/pthread_arch.h
@@ -8,4 +8,4 @@ static inline struct pthread *__pthread_self()
#define TLS_ABOVE_TP
#define TP_ADJ(p) ((char *)(p) + sizeof(struct pthread) - 8)
-#define CANCEL_REG_IP 17
+#define MC_PC sc_pc
diff --git a/arch/x32/pthread_arch.h b/arch/x32/pthread_arch.h
index 033bfd6..ecb0bbf 100644
--- a/arch/x32/pthread_arch.h
+++ b/arch/x32/pthread_arch.h
@@ -7,6 +7,6 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 32
+#define MC_PC gregs[REG_RIP]
#define CANARY canary2
diff --git a/arch/x86_64/pthread_arch.h b/arch/x86_64/pthread_arch.h
index 29e4590..c61509c 100644
--- a/arch/x86_64/pthread_arch.h
+++ b/arch/x86_64/pthread_arch.h
@@ -7,4 +7,4 @@ static inline struct pthread *__pthread_self()
#define TP_ADJ(p) (p)
-#define CANCEL_REG_IP 16
+#define MC_PC gregs[REG_RIP]
diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
index 0151a1a..6eaf72c 100644
--- a/src/thread/pthread_cancel.c
+++ b/src/thread/pthread_cancel.c
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
#include <string.h>
#include "pthread_impl.h"
#include "syscall.h"
@@ -61,15 +62,15 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
{
pthread_t self = __pthread_self();
ucontext_t *uc = ctx;
- const char *ip = ((char **)&uc->uc_mcontext)[CANCEL_REG_IP];
+ uintptr_t pc = uc->uc_mcontext.MC_PC;
a_barrier();
if (!self->cancel || self->canceldisable == PTHREAD_CANCEL_DISABLE) return;
_sigaddset(&uc->uc_sigmask, SIGCANCEL);
- if (self->cancelasync || ip >= __cp_begin && ip < __cp_end) {
- ((char **)&uc->uc_mcontext)[CANCEL_REG_IP] = (char *)__cp_cancel;
+ if (self->cancelasync || pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) {
+ uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel;
return;
}
--
2.7.0
From 36e8b6a28be5d4ffad966386b1e1c0d0dc6ca11a Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Mon, 2 Nov 2015 16:16:00 -0500
Subject: [PATCH] use explicit __cp_cancel label in cancellable syscall asm for
all archs
previously, only archs that needed to do stack cleanup defined a
__cp_cancel label for acting on cancellation in their syscall asm, and
a default definition was provided by a weak alias to __cancel, the C
function. this resulted in wrong codegen for arm on gcc versions
affected by pr 68178 and possibly similar issues (like pr 66609) on
other archs, and also created an inconsistency where the __cp_begin
and __cp_end labels were treated as const data but __cp_cancel was
treated as a function. this in turn caused incorrect code generation
on archs where function pointers point to function descriptors rather
than code (for now, only sh/fdpic).
---
src/thread/aarch64/syscall_cp.s | 7 +++----
src/thread/microblaze/syscall_cp.s | 4 +++-
src/thread/or1k/syscall_cp.s | 5 ++++-
src/thread/powerpc/syscall_cp.s | 4 +++-
src/thread/pthread_cancel.c | 10 ++--------
src/thread/sh/syscall_cp.s | 22 +++++++++++-----------
src/thread/x32/syscall_cp.s | 4 +++-
src/thread/x86_64/syscall_cp.s | 4 +++-
8 files changed, 32 insertions(+), 28 deletions(-)
diff --git a/src/thread/aarch64/syscall_cp.s b/src/thread/aarch64/syscall_cp.s
index 30e677c..41db68a 100644
--- a/src/thread/aarch64/syscall_cp.s
+++ b/src/thread/aarch64/syscall_cp.s
@@ -17,7 +17,7 @@
__syscall_cp_asm:
__cp_begin:
ldr w0,[x0]
- cbnz w0,1f
+ cbnz w0,__cp_cancel
mov x8,x1
mov x0,x2
mov x1,x3
@@ -28,6 +28,5 @@ __cp_begin:
svc 0
__cp_end:
ret
-
- // cbnz might not be able to jump far enough
-1: b __cancel
+__cp_cancel:
+ b __cancel
diff --git a/src/thread/microblaze/syscall_cp.s b/src/thread/microblaze/syscall_cp.s
index 51599c9..b0df61c 100644
--- a/src/thread/microblaze/syscall_cp.s
+++ b/src/thread/microblaze/syscall_cp.s
@@ -11,7 +11,7 @@
__syscall_cp_asm:
__cp_begin:
lwi r5, r5, 0
- bnei r5, __cancel
+ bnei r5, __cp_cancel
addi r12, r6, 0
add r5, r7, r0
add r6, r8, r0
@@ -23,3 +23,5 @@ __cp_begin:
__cp_end:
rtsd r15, 8
nop
+__cp_cancel:
+ bri __cancel
diff --git a/src/thread/or1k/syscall_cp.s b/src/thread/or1k/syscall_cp.s
index 2c0bf0e..7951166 100644
--- a/src/thread/or1k/syscall_cp.s
+++ b/src/thread/or1k/syscall_cp.s
@@ -12,7 +12,7 @@ __syscall_cp_asm:
__cp_begin:
l.lwz r3, 0(r3)
l.sfeqi r3, 0
- l.bnf __cancel
+ l.bnf __cp_cancel
l.ori r11, r4, 0
l.ori r3, r5, 0
l.ori r4, r6, 0
@@ -24,3 +24,6 @@ __cp_begin:
__cp_end:
l.jr r9
l.nop
+__cp_cancel:
+ l.j __cancel
+ l.nop
diff --git a/src/thread/powerpc/syscall_cp.s b/src/thread/powerpc/syscall_cp.s
index 20b5e0a..77f8938 100644
--- a/src/thread/powerpc/syscall_cp.s
+++ b/src/thread/powerpc/syscall_cp.s
@@ -38,7 +38,7 @@ __cp_begin:
cmpwi cr7, 0, 0 #compare r0 with 0, store result in cr7.
beq+ cr7, 1f #jump to label 1 if r0 was 0
- b __cancel #else call cancel
+ b __cp_cancel #else call cancel
1:
#ok, the cancel flag was not set
# syscall: number goes to r0, the rest 3-8
@@ -55,3 +55,5 @@ __cp_end:
#else negate result.
neg 3, 3
blr
+__cp_cancel:
+ b __cancel
diff --git a/src/thread/pthread_cancel.c b/src/thread/pthread_cancel.c
index 6eaf72c..c4631f0 100644
--- a/src/thread/pthread_cancel.c
+++ b/src/thread/pthread_cancel.c
@@ -7,7 +7,7 @@
#ifdef SHARED
__attribute__((__visibility__("hidden")))
#endif
-long __cancel(), __cp_cancel(), __syscall_cp_asm(), __syscall_cp_c();
+long __cancel(), __syscall_cp_asm(), __syscall_cp_c();
long __cancel()
{
@@ -18,12 +18,6 @@ long __cancel()
return -ECANCELED;
}
-/* If __syscall_cp_asm has adjusted the stack pointer, it must provide a
- * definition of __cp_cancel to undo those adjustments and call __cancel.
- * Otherwise, __cancel provides a definition for __cp_cancel. */
-
-weak_alias(__cancel, __cp_cancel);
-
long __syscall_cp_asm(volatile void *, syscall_arg_t,
syscall_arg_t, syscall_arg_t, syscall_arg_t,
syscall_arg_t, syscall_arg_t, syscall_arg_t);
@@ -56,7 +50,7 @@ static void _sigaddset(sigset_t *set, int sig)
#ifdef SHARED
__attribute__((__visibility__("hidden")))
#endif
-extern const char __cp_begin[1], __cp_end[1];
+extern const char __cp_begin[1], __cp_end[1], __cp_cancel[1];
static void cancel_handler(int sig, siginfo_t *si, void *ctx)
{
diff --git a/src/thread/sh/syscall_cp.s b/src/thread/sh/syscall_cp.s
index c3cafac..bb848ef 100644
--- a/src/thread/sh/syscall_cp.s
+++ b/src/thread/sh/syscall_cp.s
@@ -14,17 +14,8 @@ __syscall_cp_asm:
__cp_begin:
mov.l @r4, r4
tst r4, r4
- bt 2f
-
- mov.l L1, r0
- braf r0
- nop
-1:
-
-.align 2
-L1: .long __cancel@PLT-(1b-.)
-
-2: mov r5, r3
+ bf __cp_cancel
+ mov r5, r3
mov r6, r4
mov r7, r5
mov.l @r15, r6
@@ -43,3 +34,12 @@ __cp_end:
rts
nop
+
+__cp_cancel:
+ mov.l 2f, r0
+ braf r0
+ nop
+1:
+
+.align 2
+2: .long __cancel@PCREL-(1b-.)
diff --git a/src/thread/x32/syscall_cp.s b/src/thread/x32/syscall_cp.s
index 79709a5..9805af0 100644
--- a/src/thread/x32/syscall_cp.s
+++ b/src/thread/x32/syscall_cp.s
@@ -14,7 +14,7 @@ __syscall_cp_internal:
__cp_begin:
mov (%rdi),%eax
test %eax,%eax
- jnz __cancel
+ jnz __cp_cancel
mov %rdi,%r11
mov %rsi,%rax
mov %rdx,%rdi
@@ -27,3 +27,5 @@ __cp_begin:
syscall
__cp_end:
ret
+__cp_cancel:
+ jmp __cancel
diff --git a/src/thread/x86_64/syscall_cp.s b/src/thread/x86_64/syscall_cp.s
index 1a0fd5d..4f10171 100644
--- a/src/thread/x86_64/syscall_cp.s
+++ b/src/thread/x86_64/syscall_cp.s
@@ -14,7 +14,7 @@ __syscall_cp_asm:
__cp_begin:
mov (%rdi),%eax
test %eax,%eax
- jnz __cancel
+ jnz __cp_cancel
mov %rdi,%r11
mov %rsi,%rax
mov %rdx,%rdi
@@ -27,3 +27,5 @@ __cp_begin:
syscall
__cp_end:
ret
+__cp_cancel:
+ jmp __cancel
--
2.7.0
From f9ecb6bfa1dc9f93a10dad97a158e6b8334c586c Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Sat, 31 Oct 2015 05:14:45 -0400
Subject: [PATCH] prevent allocs than PTRDIFF_MAX via mremap
It's quite feasible for this to happen via MREMAP_MAYMOVE.
---
src/mman/mremap.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/mman/mremap.c b/src/mman/mremap.c
index 596c45f..1096ace 100644
--- a/src/mman/mremap.c
+++ b/src/mman/mremap.c
@@ -1,5 +1,7 @@
#include <unistd.h>
#include <sys/mman.h>
+#include <errno.h>
+#include <stdint.h>
#include <stdarg.h>
#include "syscall.h"
#include "libc.h"
@@ -8,7 +10,12 @@ void *__mremap(void *old_addr, size_t old_len, size_t new_len, int flags, ...)
{
va_list ap;
void *new_addr;
-
+
+ if (new_len >= PTRDIFF_MAX) {
+ errno = ENOMEM;
+ return MAP_FAILED;
+ }
+
va_start(ap, flags);
new_addr = va_arg(ap, void *);
va_end(ap);
--
2.7.0
From fda365a53074f97f3213caefe70ea13297acecb2 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Mon, 2 Nov 2015 16:37:51 -0500
Subject: [PATCH] fix mremap memory synchronization and use of variadic
argument
since mremap with the MREMAP_FIXED flag is an operation that unmaps
existing mappings, it needs to use the vm lock mechanism to ensure
that any in-progress synchronization operations using vm identities
from before the call have finished.
also, the variadic argument was erroneously being read even if the
MREMAP_FIXED flag was not passed. in practice this didn't break
anything, but it's UB and in theory LTO could turn it into a hard
error.
---
src/mman/mremap.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/mman/mremap.c b/src/mman/mremap.c
index 1096ace..ce4e8ea 100644
--- a/src/mman/mremap.c
+++ b/src/mman/mremap.c
@@ -1,3 +1,4 @@
+#define _GNU_SOURCE
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
@@ -6,19 +7,25 @@
#include "syscall.h"
#include "libc.h"
+static void dummy(void) { }
+weak_alias(dummy, __vm_wait);
+
void *__mremap(void *old_addr, size_t old_len, size_t new_len, int flags, ...)
{
va_list ap;
- void *new_addr;
+ void *new_addr = 0;
if (new_len >= PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
}
- va_start(ap, flags);
- new_addr = va_arg(ap, void *);
- va_end(ap);
+ if (flags & MREMAP_FIXED) {
+ __vm_wait();
+ va_start(ap, flags);
+ new_addr = va_arg(ap, void *);
+ va_end(ap);
+ }
return (void *)syscall(SYS_mremap, old_addr, old_len, new_len, flags, new_addr);
}
--
2.7.0
From 27c1eccf33ce5cb7508ef5e541daa9b6441b4a51 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Wed, 4 Nov 2015 13:24:11 -0500
Subject: [PATCH] have configure check/add -ffunction-sections and
-fdata-sections
based on patch by Denys Vlasenko. the original intent for using these
options was to enable linking optimizations. these are immediately
available for static linking applications to libc.a, and will also be
used for linking libc.so in a subsequent commit.
in addition to the original motives, this change works around a whole
class of toolchain bugs where the compiler generates relative address
expressions using a weak symbol and the assembler "optimizes out" the
relocation which should result by using the weak definition. (see gas
pr 18561 and gcc pr 66609, 68178, etc. for examples.) by having
different functions and data objects in their own sections, all
relative address expressions are cross-section and thus cannot be
resolved to constants until link time. this allows us to retain
support for affected compiler/assembler versions without invasive
and fragile source-level workarounds.
---
configure | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/configure b/configure
index 3e536f5..1e5c4b3 100755
--- a/configure
+++ b/configure
@@ -437,6 +437,17 @@ tryflag CFLAGS_AUTO -fno-unwind-tables
tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables
#
+# Attempt to put each function and each data object in its own
+# section. This both allows additional size optimizations at link
+# time and works around a dangerous class of compiler/assembler bugs
+# whereby relative address expressions are constant-folded by the
+# assembler even when one or more of the symbols involved is
+# replaceable. See gas pr 18561 and gcc pr 66609, 68178, etc.
+#
+tryflag CFLAGS_AUTO -ffunction-sections
+tryflag CFLAGS_AUTO -fdata-sections
+
+#
# On x86, make sure we don't have incompatible instruction set