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:
32
misc/sbrk.c
32
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;
|
||||
/* 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))
|
||||
|
Reference in New Issue
Block a user