mirror of git://sourceware.org/git/glibc.git
elf: early conversion of elf p_flags to mprotect flags
This patch replaces _dl_stack_flags global variable by _dl_stack_prot_flags. The advantage is that any convertion from p_flags to final used mprotect flags occurs at loading of p_flags. It avoids repeated spurious convertions of _dl_stack_flags, for example in allocate_thread_stack. This modification was suggested in: https://sourceware.org/pipermail/libc-alpha/2025-March/165537.html Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
parent
921e251e8f
commit
3b2b88ccee
|
|
@ -2167,7 +2167,7 @@ $(objpfx)execstack-default: $(first-word $(wildcard $(sysdirs:%=%/stackinfo.h)))
|
||||||
$(make-target-directory)
|
$(make-target-directory)
|
||||||
{ echo '#include <elf.h>'; \
|
{ echo '#include <elf.h>'; \
|
||||||
echo '#include <stackinfo.h>'; \
|
echo '#include <stackinfo.h>'; \
|
||||||
echo '#if (DEFAULT_STACK_PERMS & PF_X) == 0'; \
|
echo '#if (DEFAULT_STACK_PROT_PERMS & PROT_EXEC) == 0'; \
|
||||||
echo '@@@execstack-no@@@'; \
|
echo '@@@execstack-no@@@'; \
|
||||||
echo '#else'; \
|
echo '#else'; \
|
||||||
echo '@@@execstack-yes@@@'; \
|
echo '@@@execstack-yes@@@'; \
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ _dl_handle_execstack_tunable (void)
|
||||||
switch (TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL))
|
switch (TUNABLE_GET (glibc, rtld, execstack, int32_t, NULL))
|
||||||
{
|
{
|
||||||
case stack_tunable_mode_disable:
|
case stack_tunable_mode_disable:
|
||||||
if ((__glibc_unlikely (GL(dl_stack_flags)) & PF_X))
|
if ((__glibc_unlikely (GL(dl_stack_prot_flags)) & PROT_EXEC))
|
||||||
_dl_fatal_printf (
|
_dl_fatal_printf (
|
||||||
"Fatal glibc error: executable stack is not allowed\n");
|
"Fatal glibc error: executable stack is not allowed\n");
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -1095,7 +1095,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
/* On most platforms presume that PT_GNU_STACK is absent and the stack is
|
/* On most platforms presume that PT_GNU_STACK is absent and the stack is
|
||||||
* executable. Other platforms default to a nonexecutable stack and don't
|
* executable. Other platforms default to a nonexecutable stack and don't
|
||||||
* need PT_GNU_STACK to do so. */
|
* need PT_GNU_STACK to do so. */
|
||||||
unsigned int stack_flags = DEFAULT_STACK_PERMS;
|
unsigned int stack_flags = DEFAULT_STACK_PROT_PERMS;
|
||||||
|
|
||||||
{
|
{
|
||||||
/* Scan the program header table, collecting its load commands. */
|
/* Scan the program header table, collecting its load commands. */
|
||||||
|
|
@ -1170,18 +1170,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
DIAG_POP_NEEDS_COMMENT;
|
DIAG_POP_NEEDS_COMMENT;
|
||||||
|
|
||||||
/* Optimize a common case. */
|
/* Optimize a common case. */
|
||||||
#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
|
c->prot = pf_to_prot (ph->p_flags);
|
||||||
c->prot = (PF_TO_PROT
|
|
||||||
>> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
|
|
||||||
#else
|
|
||||||
c->prot = 0;
|
|
||||||
if (ph->p_flags & PF_R)
|
|
||||||
c->prot |= PROT_READ;
|
|
||||||
if (ph->p_flags & PF_W)
|
|
||||||
c->prot |= PROT_WRITE;
|
|
||||||
if (ph->p_flags & PF_X)
|
|
||||||
c->prot |= PROT_EXEC;
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_TLS:
|
case PT_TLS:
|
||||||
|
|
@ -1218,7 +1207,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_GNU_STACK:
|
case PT_GNU_STACK:
|
||||||
stack_flags = ph->p_flags;
|
stack_flags = pf_to_prot (ph->p_flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_GNU_RELRO:
|
case PT_GNU_RELRO:
|
||||||
|
|
@ -1318,7 +1307,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
|
||||||
/* Adjust the PT_PHDR value by the runtime load address. */
|
/* Adjust the PT_PHDR value by the runtime load address. */
|
||||||
l->l_phdr = (ElfW(Phdr) *) ((ElfW(Addr)) l->l_phdr + l->l_addr);
|
l->l_phdr = (ElfW(Phdr) *) ((ElfW(Addr)) l->l_phdr + l->l_addr);
|
||||||
|
|
||||||
if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_flags)) & PF_X))
|
if (__glibc_unlikely ((stack_flags &~ GL(dl_stack_prot_flags)) & PROT_EXEC))
|
||||||
{
|
{
|
||||||
/* The stack is presently not executable, but this module
|
/* The stack is presently not executable, but this module
|
||||||
requires that it be executable. Only tries to change the
|
requires that it be executable. Only tries to change the
|
||||||
|
|
|
||||||
|
|
@ -166,9 +166,8 @@ enum dso_sort_algorithm _dl_dso_sort_algo;
|
||||||
/* The value of the FPU control word the kernel will preset in hardware. */
|
/* The value of the FPU control word the kernel will preset in hardware. */
|
||||||
fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
|
fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
|
||||||
|
|
||||||
/* Prevailing state of the stack. Generally this includes PF_X, indicating it's
|
/* Required flags used for stack allocation. */
|
||||||
* executable but this isn't true for all platforms. */
|
int _dl_stack_prot_flags = DEFAULT_STACK_PROT_PERMS;
|
||||||
ElfW(Word) _dl_stack_flags = DEFAULT_STACK_PERMS;
|
|
||||||
|
|
||||||
#if PTHREAD_IN_LIBC
|
#if PTHREAD_IN_LIBC
|
||||||
list_t _dl_stack_used;
|
list_t _dl_stack_used;
|
||||||
|
|
@ -322,7 +321,7 @@ _dl_non_dynamic_init (void)
|
||||||
{
|
{
|
||||||
/* Check if the stack is nonexecutable. */
|
/* Check if the stack is nonexecutable. */
|
||||||
case PT_GNU_STACK:
|
case PT_GNU_STACK:
|
||||||
_dl_stack_flags = ph->p_flags;
|
_dl_stack_prot_flags = pf_to_prot (ph->p_flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_GNU_RELRO:
|
case PT_GNU_RELRO:
|
||||||
|
|
|
||||||
12
elf/rtld.c
12
elf/rtld.c
|
|
@ -322,7 +322,7 @@ struct rtld_global _rtld_global =
|
||||||
#include <dl-procruntime.c>
|
#include <dl-procruntime.c>
|
||||||
/* Generally the default presumption without further information is an
|
/* Generally the default presumption without further information is an
|
||||||
* executable stack but this is not true for all platforms. */
|
* executable stack but this is not true for all platforms. */
|
||||||
._dl_stack_flags = DEFAULT_STACK_PERMS,
|
._dl_stack_prot_flags = DEFAULT_STACK_PROT_PERMS,
|
||||||
#ifdef _LIBC_REENTRANT
|
#ifdef _LIBC_REENTRANT
|
||||||
._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||||
._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
|
||||||
|
|
@ -1197,7 +1197,7 @@ rtld_setup_main_map (struct link_map *main_map)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_GNU_STACK:
|
case PT_GNU_STACK:
|
||||||
GL(dl_stack_flags) = ph->p_flags;
|
GL(dl_stack_prot_flags) = pf_to_prot (ph->p_flags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_GNU_RELRO:
|
case PT_GNU_RELRO:
|
||||||
|
|
@ -1541,12 +1541,12 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
--_dl_argc;
|
--_dl_argc;
|
||||||
++_dl_argv;
|
++_dl_argv;
|
||||||
|
|
||||||
/* The initialization of _dl_stack_flags done below assumes the
|
/* The initialization of dl_stack_prot_flags done below assumes the
|
||||||
executable's PT_GNU_STACK may have been honored by the kernel, and
|
executable's PT_GNU_STACK may have been honored by the kernel, and
|
||||||
so a PT_GNU_STACK with PF_X set means the stack started out with
|
so a PT_GNU_STACK with PF_X set means the stack started out with
|
||||||
execute permission. However, this is not really true if the
|
execute permission. However, this is not really true if the
|
||||||
dynamic linker is the executable the kernel loaded. For this
|
dynamic linker is the executable the kernel loaded. For this
|
||||||
case, we must reinitialize _dl_stack_flags to match the dynamic
|
case, we must reinitialize dl_stack_prot_flags to match the dynamic
|
||||||
linker itself. If the dynamic linker was built with a
|
linker itself. If the dynamic linker was built with a
|
||||||
PT_GNU_STACK, then the kernel may have loaded us with a
|
PT_GNU_STACK, then the kernel may have loaded us with a
|
||||||
nonexecutable stack that we will have to make executable when we
|
nonexecutable stack that we will have to make executable when we
|
||||||
|
|
@ -1556,7 +1556,7 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
for (const ElfW(Phdr) *ph = phdr; ph < &phdr[phnum]; ++ph)
|
for (const ElfW(Phdr) *ph = phdr; ph < &phdr[phnum]; ++ph)
|
||||||
if (ph->p_type == PT_GNU_STACK)
|
if (ph->p_type == PT_GNU_STACK)
|
||||||
{
|
{
|
||||||
GL(dl_stack_flags) = ph->p_flags;
|
GL(dl_stack_prot_flags) = pf_to_prot (ph->p_flags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1677,8 +1677,6 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
|
||||||
bool has_interp = rtld_setup_main_map (main_map);
|
bool has_interp = rtld_setup_main_map (main_map);
|
||||||
|
|
||||||
/* Handle this after PT_GNU_STACK parse, because it updates dl_stack_flags
|
|
||||||
if required. */
|
|
||||||
_dl_handle_execstack_tunable ();
|
_dl_handle_execstack_tunable ();
|
||||||
|
|
||||||
/* If the current libname is different from the SONAME, add the
|
/* If the current libname is different from the SONAME, add the
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
# ifndef _ISOMAC
|
# ifndef _ISOMAC
|
||||||
|
|
||||||
#include <stackinfo.h>
|
#include <elf.h>
|
||||||
|
|
||||||
#undef __alloca
|
#undef __alloca
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,4 +39,38 @@
|
||||||
# error "stackinfo.h must define _STACK_GROWS_UP or _STACK_GROWS_DOWN!"
|
# error "stackinfo.h must define _STACK_GROWS_UP or _STACK_GROWS_DOWN!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <link.h>
|
||||||
|
|
||||||
|
/* ELF uses the PF_x macros to specify the segment permissions, mmap
|
||||||
|
uses PROT_xxx. In most cases the three macros have the values 1, 2,
|
||||||
|
and 4 but not in a matching order. The following macros allows
|
||||||
|
converting from the PF_x values to PROT_xxx values. */
|
||||||
|
#define PF_TO_PROT \
|
||||||
|
((PROT_READ << (PF_R * 4)) \
|
||||||
|
| (PROT_WRITE << (PF_W * 4)) \
|
||||||
|
| (PROT_EXEC << (PF_X * 4)) \
|
||||||
|
| ((PROT_READ | PROT_WRITE) << ((PF_R | PF_W) * 4)) \
|
||||||
|
| ((PROT_READ | PROT_EXEC) << ((PF_R | PF_X) * 4)) \
|
||||||
|
| ((PROT_WRITE | PROT_EXEC) << (PF_W | PF_X) * 4) \
|
||||||
|
| ((PROT_READ | PROT_WRITE | PROT_EXEC) << ((PF_R | PF_W | PF_X) * 4)))
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
pf_to_prot (ElfW(Word) value)
|
||||||
|
{
|
||||||
|
#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
|
||||||
|
return (PF_TO_PROT >> ((value & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
|
||||||
|
#else
|
||||||
|
ElfW(Word) ret = 0;
|
||||||
|
if (value & PF_R)
|
||||||
|
ret |= PROT_READ;
|
||||||
|
if (value & PF_W)
|
||||||
|
ret |= PROT_WRITE;
|
||||||
|
if (value & PF_X)
|
||||||
|
ret |= PROT_EXEC;
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* include/stackinfo.h */
|
#endif /* include/stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -150,17 +150,11 @@ get_cached_stack (size_t *sizep, void **memp)
|
||||||
and fallback to ALLOCATE_GUARD_PROT_NONE if the madvise call fails. */
|
and fallback to ALLOCATE_GUARD_PROT_NONE if the madvise call fails. */
|
||||||
static int allocate_stack_mode = ALLOCATE_GUARD_MADV_GUARD;
|
static int allocate_stack_mode = ALLOCATE_GUARD_MADV_GUARD;
|
||||||
|
|
||||||
static inline int stack_prot (void)
|
|
||||||
{
|
|
||||||
return (PROT_READ | PROT_WRITE
|
|
||||||
| ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
allocate_thread_stack (size_t size, size_t guardsize)
|
allocate_thread_stack (size_t size, size_t guardsize)
|
||||||
{
|
{
|
||||||
/* MADV_ADVISE_GUARD does not require an additional PROT_NONE mapping. */
|
/* MADV_ADVISE_GUARD does not require an additional PROT_NONE mapping. */
|
||||||
int prot = stack_prot ();
|
int prot = GL(dl_stack_prot_flags);
|
||||||
|
|
||||||
if (atomic_load_relaxed (&allocate_stack_mode) == ALLOCATE_GUARD_PROT_NONE)
|
if (atomic_load_relaxed (&allocate_stack_mode) == ALLOCATE_GUARD_PROT_NONE)
|
||||||
/* If a guard page is required, avoid committing memory by first allocate
|
/* If a guard page is required, avoid committing memory by first allocate
|
||||||
|
|
@ -216,7 +210,7 @@ setup_stack_prot (char *mem, size_t size, struct pthread *pd,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const int prot = stack_prot ();
|
const int prot = GL(dl_stack_prot_flags);
|
||||||
char *guardend = guard + guardsize;
|
char *guardend = guard + guardsize;
|
||||||
#if _STACK_GROWS_DOWN
|
#if _STACK_GROWS_DOWN
|
||||||
/* As defined at guard_position, for architectures with downward stack
|
/* As defined at guard_position, for architectures with downward stack
|
||||||
|
|
@ -294,7 +288,7 @@ adjust_stack_prot (char *mem, size_t size, const struct pthread *pd,
|
||||||
}
|
}
|
||||||
else if (pd->stack_mode == ALLOCATE_GUARD_PROT_NONE)
|
else if (pd->stack_mode == ALLOCATE_GUARD_PROT_NONE)
|
||||||
{
|
{
|
||||||
const int prot = stack_prot ();
|
const int prot = GL(dl_stack_prot_flags);
|
||||||
#if _STACK_GROWS_DOWN
|
#if _STACK_GROWS_DOWN
|
||||||
return __mprotect (mem + guardsize, slacksize, prot) == 0;
|
return __mprotect (mem + guardsize, slacksize, prot) == 0;
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,10 @@ support_stack_alloc (size_t size)
|
||||||
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE|MAP_STACK,
|
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE|MAP_STACK,
|
||||||
-1);
|
-1);
|
||||||
/* Some architecture still requires executable stack for the signal return
|
/* Some architecture still requires executable stack for the signal return
|
||||||
trampoline, although PF_X could be overridden if PT_GNU_STACK is present.
|
trampoline, although PROT_EXEC could be overridden if PT_GNU_STACK is
|
||||||
However since glibc does not export such information with a proper ABI,
|
present. However since glibc does not export such information with a
|
||||||
it uses the historical permissions. */
|
proper ABI, it uses the historical permissions. */
|
||||||
int prot = PROT_READ | PROT_WRITE
|
int prot = DEFAULT_STACK_PROT_PERMS;
|
||||||
| (DEFAULT_STACK_PERMS & PF_X ? PROT_EXEC : 0);
|
|
||||||
xmprotect (alloc_base + guardsize, stacksize, prot);
|
xmprotect (alloc_base + guardsize, stacksize, prot);
|
||||||
memset (alloc_base + guardsize, 0xA5, stacksize);
|
memset (alloc_base + guardsize, 0xA5, stacksize);
|
||||||
return (struct support_stack) { alloc_base + guardsize, stacksize, guardsize };
|
return (struct support_stack) { alloc_base + guardsize, stacksize, guardsize };
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
/* On Alpha the stack grows down. */
|
/* On Alpha the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
/* On Arm the stack grows down. */
|
/* On Arm the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -171,19 +171,6 @@ dl_symbol_visibility_binds_local_p (const ElfW(Sym) *sym)
|
||||||
# define ELF_RTYPE_CLASS_COPY 0
|
# define ELF_RTYPE_CLASS_COPY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ELF uses the PF_x macros to specify the segment permissions, mmap
|
|
||||||
uses PROT_xxx. In most cases the three macros have the values 1, 2,
|
|
||||||
and 3 but not in a matching order. The following macros allows
|
|
||||||
converting from the PF_x values to PROT_xxx values. */
|
|
||||||
#define PF_TO_PROT \
|
|
||||||
((PROT_READ << (PF_R * 4)) \
|
|
||||||
| (PROT_WRITE << (PF_W * 4)) \
|
|
||||||
| (PROT_EXEC << (PF_X * 4)) \
|
|
||||||
| ((PROT_READ | PROT_WRITE) << ((PF_R | PF_W) * 4)) \
|
|
||||||
| ((PROT_READ | PROT_EXEC) << ((PF_R | PF_X) * 4)) \
|
|
||||||
| ((PROT_WRITE | PROT_EXEC) << (PF_W | PF_X) * 4) \
|
|
||||||
| ((PROT_READ | PROT_WRITE | PROT_EXEC) << ((PF_R | PF_W | PF_X) * 4)))
|
|
||||||
|
|
||||||
/* The filename itself, or the main program name, if available. */
|
/* The filename itself, or the main program name, if available. */
|
||||||
#define DSO_FILENAME(name) ((name)[0] ? (name) \
|
#define DSO_FILENAME(name) ((name)[0] ? (name) \
|
||||||
: (rtld_progname ?: "<main program>"))
|
: (rtld_progname ?: "<main program>"))
|
||||||
|
|
@ -416,7 +403,7 @@ struct rtld_global
|
||||||
#include <dl-procruntime.c>
|
#include <dl-procruntime.c>
|
||||||
|
|
||||||
/* Prevailing state of the stack, PF_X indicating it's executable. */
|
/* Prevailing state of the stack, PF_X indicating it's executable. */
|
||||||
EXTERN ElfW(Word) _dl_stack_flags;
|
EXTERN int _dl_stack_prot_flags;
|
||||||
|
|
||||||
/* Flag signalling whether there are gaps in the module ID allocation. */
|
/* Flag signalling whether there are gaps in the module ID allocation. */
|
||||||
EXTERN bool _dl_tls_dtv_gaps;
|
EXTERN bool _dl_tls_dtv_gaps;
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,6 @@
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,9 @@
|
||||||
|
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
/* On PA the stack grows up. */
|
/* On PA the stack grows up. */
|
||||||
#define _STACK_GROWS_UP 1
|
#define _STACK_GROWS_UP 1
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@
|
||||||
/* On x86 the stack grows down. */
|
/* On x86 the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
/* Access to the stack pointer. The macros are used in alloca_account
|
/* Access to the stack pointer. The macros are used in alloca_account
|
||||||
for which they need to act as barriers as well, hence the additional
|
for which they need to act as barriers as well, hence the additional
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@
|
||||||
/* On m68k the stack grows down. */
|
/* On m68k the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
is present, but it is presumed absent. */
|
is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
/* Access to the stack pointer. */
|
/* Access to the stack pointer. */
|
||||||
#define stackinfo_get_sp() \
|
#define stackinfo_get_sp() \
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ __pthread_stack_alloc (void **stackaddr, size_t stacksize)
|
||||||
error_t err;
|
error_t err;
|
||||||
vm_prot_t prot = VM_PROT_READ | VM_PROT_WRITE;
|
vm_prot_t prot = VM_PROT_READ | VM_PROT_WRITE;
|
||||||
|
|
||||||
if (GL(dl_stack_flags) & PF_X)
|
if (GL(dl_stack_prot_flags) & PROT_EXEC)
|
||||||
prot |= VM_PROT_EXECUTE;
|
prot |= VM_PROT_EXECUTE;
|
||||||
|
|
||||||
err = __vm_map (__mach_task_self (), (vm_offset_t *) stackaddr,
|
err = __vm_map (__mach_task_self (), (vm_offset_t *) stackaddr,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ _dl_make_stack_executable (const void *stack_endp)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
/* Remember that we changed the permission. */
|
/* Remember that we changed the permission. */
|
||||||
GL(dl_stack_flags) |= PF_X;
|
GL(dl_stack_prot_flags) |= PROT_EXEC;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <pt-internal.h>
|
#include <pt-internal.h>
|
||||||
#include <pthreadP.h>
|
#include <pthreadP.h>
|
||||||
|
#include <stackinfo.h>
|
||||||
|
|
||||||
static void
|
static void
|
||||||
reset_pthread_total (void)
|
reset_pthread_total (void)
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@
|
||||||
/* On MicroBlaze the stack grows down. */
|
/* On MicroBlaze the stack grows down. */
|
||||||
# define _STACK_GROWS_DOWN 1
|
# define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
# define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h. */
|
#endif /* stackinfo.h. */
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
/* On MIPS the stack grows down. */
|
/* On MIPS the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,8 @@
|
||||||
/* On or1k the stack grows down. */
|
/* On or1k the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
present, but it is presumed absent. */
|
is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R | PF_W | PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@
|
||||||
/* On PPC the stack grows down. */
|
/* On PPC the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* PF_X can be overridden if PT_GNU_STACK is present but is presumed absent. */
|
/* PROT_EXEC can be overridden if PT_GNU_STACK is present but is presumed
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
absent. */
|
||||||
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
/* On s390 the stack grows down. */
|
/* On s390 the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
/* On SH the stack grows down. */
|
/* On SH the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
/* On sparc the stack grows down. */
|
/* On sparc the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
#endif /* stackinfo.h */
|
#endif /* stackinfo.h */
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
<https://www.gnu.org/licenses/>. */
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
|
#include <stackinfo.h>
|
||||||
|
|
||||||
int
|
int
|
||||||
_dl_make_stack_executable (const void *stack_endp)
|
_dl_make_stack_executable (const void *stack_endp)
|
||||||
|
|
@ -36,7 +37,7 @@ _dl_make_stack_executable (const void *stack_endp)
|
||||||
return errno;
|
return errno;
|
||||||
|
|
||||||
/* Remember that we changed the permission. */
|
/* Remember that we changed the permission. */
|
||||||
GL(dl_stack_flags) |= PF_X;
|
GL(dl_stack_prot_flags) |= PROT_EXEC;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
#ifndef _MACHINE_SP_H
|
#ifndef _MACHINE_SP_H
|
||||||
#define _MACHINE_SP_H
|
#define _MACHINE_SP_H
|
||||||
|
|
||||||
|
#include <stackinfo.h>
|
||||||
|
|
||||||
/* Return the current stack pointer. */
|
/* Return the current stack pointer. */
|
||||||
static inline uintptr_t
|
static inline uintptr_t
|
||||||
__thread_stack_pointer (void)
|
__thread_stack_pointer (void)
|
||||||
|
|
|
||||||
|
|
@ -348,9 +348,6 @@ __spawnix (int *pid, const char *file,
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
int prot = (PROT_READ | PROT_WRITE
|
|
||||||
| ((GL (dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
|
|
||||||
|
|
||||||
/* Add a slack area for child's stack. */
|
/* Add a slack area for child's stack. */
|
||||||
size_t argv_size = (argc * sizeof (void *)) + 512;
|
size_t argv_size = (argc * sizeof (void *)) + 512;
|
||||||
/* We need at least a few pages in case the compiler's stack checking is
|
/* We need at least a few pages in case the compiler's stack checking is
|
||||||
|
|
@ -361,7 +358,7 @@ __spawnix (int *pid, const char *file,
|
||||||
where it might use about 1k extra stack space). */
|
where it might use about 1k extra stack space). */
|
||||||
argv_size += (32 * 1024);
|
argv_size += (32 * 1024);
|
||||||
size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
|
size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
|
||||||
void *stack = __mmap (NULL, stack_size, prot,
|
void *stack = __mmap (NULL, stack_size, GL (dl_stack_prot_flags),
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
|
||||||
if (__glibc_unlikely (stack == MAP_FAILED))
|
if (__glibc_unlikely (stack == MAP_FAILED))
|
||||||
return errno;
|
return errno;
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,9 @@
|
||||||
/* On x86_64 the stack grows down. */
|
/* On x86_64 the stack grows down. */
|
||||||
#define _STACK_GROWS_DOWN 1
|
#define _STACK_GROWS_DOWN 1
|
||||||
|
|
||||||
/* Default to an executable stack. PF_X can be overridden if PT_GNU_STACK is
|
/* Default to an executable stack. PROT_EXEC can be overridden if PT_GNU_STACK
|
||||||
* present, but it is presumed absent. */
|
* is present, but it is presumed absent. */
|
||||||
#define DEFAULT_STACK_PERMS (PF_R|PF_W|PF_X)
|
#define DEFAULT_STACK_PROT_PERMS (PROT_READ|PROT_WRITE|PROT_EXEC)
|
||||||
|
|
||||||
/* Access to the stack pointer. The macros are used in alloca_account
|
/* Access to the stack pointer. The macros are used in alloca_account
|
||||||
for which they need to act as barriers as well, hence the additional
|
for which they need to act as barriers as well, hence the additional
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue