* allocatestack.c (change_stack_perm): Split out from
	__make_stacks_executable.
	(allocate_stack): If the required permission changed between the time
	we started preparing the stack and queueing it, change the permission.
	(__make_stacks_executable): Call change_stack_perm.
This commit is contained in:
Ulrich Drepper 2003-09-25 03:16:53 +00:00
parent 9771695416
commit 279f1143af
2 changed files with 58 additions and 14 deletions

View File

@ -1,5 +1,11 @@
2003-09-24 Ulrich Drepper <drepper@redhat.com>
* allocatestack.c (change_stack_perm): Split out from
__make_stacks_executable.
(allocate_stack): If the required permission changed between the time
we started preparing the stack and queueing it, change the permission.
(__make_stacks_executable): Call change_stack_perm.
* Makefile: Build tst-execstack-mod locally.
* tst-execstack-mod.c: New file.

View File

@ -249,6 +249,29 @@ queue_stack (struct pthread *stack)
}
static int
internal_function
change_stack_perm (struct pthread *pd
#ifdef NEED_SEPARATE_REGISTER_STACK
, size_t pagemask
#endif
)
{
#ifdef NEED_SEPARATE_REGISTER_STACK
void *stack = (pd->stackblock
+ (((((pd->stackblock_size - pd->guardsize) / 2)
& pagemask) + pd->guardsize) & pagemask));
size_t len = pd->stackblock + pd->stackblock_size - stack;
#else
void *stack = pd->stackblock + pd->guardsize;
size_t len = pd->stackblock_size - pd->guardsize;
#endif
if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
return errno;
return 0;
}
static int
allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
@ -493,6 +516,28 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
lll_unlock (stack_cache_lock);
/* There might have been a race. Another thread might have
caused the stacks to get exec permission while this new
stack was prepared. Detect if this was possible and
change the permission if necessary. */
if (__builtin_expect ((GL(dl_stack_flags) & PF_X) != 0
&& (prot & PROT_EXEC) == 0, 0))
{
int err = change_stack_perm (pd
#ifdef NEED_SEPARATE_REGISTER_STACK
, ~pagesize_m1
#endif
);
if (err != 0)
{
/* Free the stack memory we just allocated. */
(void) munmap (mem, size);
return err;
}
}
/* Note that all of the stack and the thread descriptor is
zeroed. This means we do not have to initialize fields
with initial value zero. This is specifically true for
@ -630,25 +675,18 @@ __make_stacks_executable (void)
list_t *runp;
list_for_each (runp, &stack_used)
{
struct pthread *const pd = list_entry (runp, struct pthread, list);
err = change_stack_perm (list_entry (runp, struct pthread, list)
#ifdef NEED_SEPARATE_REGISTER_STACK
void *stack = (pd->stackblock
+ (((((pd->stackblock_size - pd->guardsize) / 2)
& pagemask) + pd->guardsize) & pagemask));
size_t len = pd->stackblock + pd->stackblock_size - stack;
#else
void *stack = pd->stackblock + pd->guardsize;
size_t len = pd->stackblock_size - pd->guardsize;
, pagemask
#endif
if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
{
err = errno;
);
if (err != 0)
break;
}
}
lll_unlock (stack_cache_lock);
if (err == 0)
_dl_make_stack_executable ();
return err;