aboutsummaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2020-12-16 15:09:52 +0100
committerFlorian Weimer <fweimer@redhat.com>2020-12-16 15:13:40 +0100
commite7570f4131a6af9405af7b4fd1c31de807e7cf68 (patch)
tree0f11050a7a1b768fb0d683dc60412bc2a101c3a5 /misc
parent9459fe9da0f981f77ba931790f82e43ac552b73c (diff)
downloadglibc-e7570f4131a6af9405af7b4fd1c31de807e7cf68.zip
glibc-e7570f4131a6af9405af7b4fd1c31de807e7cf68.tar.gz
glibc-e7570f4131a6af9405af7b4fd1c31de807e7cf68.tar.bz2
Replace __libc_multiple_libcs with __libc_initial flag
Change sbrk to fail for !__libc_initial (in the generic implementation). As a result, sbrk is (relatively) safe to use for the __libc_initial case (from the main libc). It is therefore no longer necessary to avoid using it in that case (or updating the brk cache), and the __libc_initial flag does not need to be updated as part of dlmopen or static dlopen. As before, direct brk system calls on Linux may lead to memory corruption. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'misc')
-rw-r--r--misc/sbrk.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/misc/sbrk.c b/misc/sbrk.c
index ba3322f..a6929d7 100644
--- a/misc/sbrk.c
+++ b/misc/sbrk.c
@@ -16,9 +16,10 @@
<https://www.gnu.org/licenses/>. */
#include <errno.h>
+#include <libc-internal.h>
+#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
-#include <libc-internal.h>
/* Defined in brk.c. */
extern void *__curbrk;
@@ -30,21 +31,34 @@ extern int __brk (void *addr);
void *
__sbrk (intptr_t increment)
{
- void *oldbrk;
-
- /* If this is not part of the dynamic library or the library is used
- via dynamic loading in a statically linked program update
- __curbrk from the kernel's brk value. That way two separate
- instances of __brk and __sbrk can share the heap, returning
- interleaved pieces of it. */
- if (__curbrk == NULL || __libc_multiple_libcs)
+ /* Controls whether __brk (0) is called to read the brk value from
+ the kernel. */
+ bool update_brk = __curbrk == NULL;
+
+#if defined (SHARED) && ! IS_IN (rtld)
+ if (!__libc_initial)
+ {
+ if (increment != 0)
+ {
+ /* Do not allow changing the brk from an inner libc because
+ it cannot be synchronized with the outer libc's brk. */
+ __set_errno (ENOMEM);
+ return (void *) -1;
+ }
+ /* Querying the kernel's brk value from an inner namespace is
+ fine. */
+ update_brk = true;
+ }
+#endif
+
+ if (update_brk)
if (__brk (0) < 0) /* Initialize the break. */
return (void *) -1;
if (increment == 0)
return __curbrk;
- oldbrk = __curbrk;
+ void *oldbrk = __curbrk;
if (increment > 0
? ((uintptr_t) oldbrk + (uintptr_t) increment < (uintptr_t) oldbrk)
: ((uintptr_t) oldbrk < (uintptr_t) -increment))