Add a check whether the stack is executable when needed, and one whether
the stack is non-executable if not explicitely enabled. The latter one is not enabled in the Makefile yet because it cannot succeed on platforms where the non-exec stack is not implemented. Both checks rely on the fact that gcc puts trampoline onto the stack for nested functions. On platforms where no such trampolines are used, no meaningful results can be expected. While not perfect, this is much easier than hand-coding trampolines for each CPU type.
This commit is contained in:
parent
d11f9c3d61
commit
7e4c34eca1
@ -1,5 +1,5 @@
|
||||
# $NetBSD: Makefile,v 1.1 1999/06/19 00:53:32 thorpej Exp $
|
||||
# $NetBSD: Makefile,v 1.2 2003/12/10 13:24:59 drochner Exp $
|
||||
|
||||
SUBDIR+= mmap
|
||||
SUBDIR+= mmap stack_exec
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
14
regress/sys/uvm/stack_exec/Makefile
Normal file
14
regress/sys/uvm/stack_exec/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# $NetBSD: Makefile,v 1.1 2003/12/10 13:24:59 drochner Exp $
|
||||
|
||||
NOMAN= #
|
||||
PROG= tramptest
|
||||
LDADD= -lpthread
|
||||
|
||||
regress:
|
||||
@if ./tramptest; then \
|
||||
echo "PASSED"; \
|
||||
else \
|
||||
echo "FAILED"; \
|
||||
fi
|
||||
|
||||
.include <bsd.prog.mk>
|
44
regress/sys/uvm/stack_exec/tramptest.c
Normal file
44
regress/sys/uvm/stack_exec/tramptest.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* $NetBSD: tramptest.c,v 1.1 2003/12/10 13:24:59 drochner Exp $ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* This test checks whether processes/threads get execute permission
|
||||
* on the stack if needed, in particular for multiple threads.
|
||||
* It depends on the fact that gcc puts trampoline code for
|
||||
* nested functions on the stack and requests execution permission
|
||||
* for that address internally, at least on some architectures.
|
||||
* (On the other architectures, the test is just insignificant.)
|
||||
* Actually, it would be better if gcc wouldn't use stack trampolines,
|
||||
* at all, but for now it allows for an easy portable check whether the
|
||||
* kernel handles permissions correctly.
|
||||
*/
|
||||
|
||||
void
|
||||
buserr(int s)
|
||||
{
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t t1, t2;
|
||||
|
||||
void *mist(void *p)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
signal(SIGBUS, buserr);
|
||||
|
||||
pthread_create(&t1, 0, mist, 0);
|
||||
pthread_create(&t2, 0, mist, 0);
|
||||
pthread_join(t1, 0);
|
||||
pthread_join(t2, 0);
|
||||
exit(0);
|
||||
}
|
13
regress/sys/uvm/stack_noexec/Makefile
Normal file
13
regress/sys/uvm/stack_noexec/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# $NetBSD: Makefile,v 1.1 2003/12/10 13:24:59 drochner Exp $
|
||||
|
||||
NOMAN= #
|
||||
PROG= tramptest
|
||||
|
||||
regress:
|
||||
@if ./tramptest; then \
|
||||
echo "PASSED"; \
|
||||
else \
|
||||
echo "FAILED"; \
|
||||
fi
|
||||
|
||||
.include <bsd.prog.mk>
|
54
regress/sys/uvm/stack_noexec/tramptest.c
Normal file
54
regress/sys/uvm/stack_noexec/tramptest.c
Normal file
@ -0,0 +1,54 @@
|
||||
/* $NetBSD: tramptest.c,v 1.1 2003/12/10 13:24:59 drochner Exp $ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
* This test checks that the stack has no execute permission.
|
||||
* It depends on the fact that gcc puts trampoline code for
|
||||
* nested functions on the stack, at least on some architectures.
|
||||
* (On the other architectures, the test will fail, as on platforms
|
||||
* where execution permissions cannot be controlled.)
|
||||
* Actually, it would be better if gcc wouldn't use stack trampolines,
|
||||
* at all, but for now it allows for an easy portable check whether the
|
||||
* stack is executable.
|
||||
*/
|
||||
|
||||
void
|
||||
__enable_execute_stack()
|
||||
{
|
||||
/* replace gcc's internal function by a noop */
|
||||
}
|
||||
|
||||
void
|
||||
buserr(int s)
|
||||
{
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void (*f)(void);
|
||||
|
||||
void do_f()
|
||||
{
|
||||
|
||||
(*f)();
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
|
||||
void mist()
|
||||
{
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
signal(SIGBUS, buserr);
|
||||
|
||||
f = mist;
|
||||
do_f();
|
||||
|
||||
exit(1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user