1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-07 06:43:00 +03:00

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>
This commit is contained in:
Florian Weimer
2020-12-16 15:09:52 +01:00
parent 9459fe9da0
commit e7570f4131
9 changed files with 52 additions and 39 deletions

View File

@@ -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;
/* Controls whether __brk (0) is called to read the brk value from
the kernel. */
bool update_brk = __curbrk == NULL;
/* 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)
#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))