tests: Add stack grows tests

Reviewed by:		kib
Differential Revision:	https://reviews.freebsd.org/D41320
MFC after:		2 weeks
This commit is contained in:
Dmitry Chagin 2023-08-08 18:12:09 +03:00
parent 58a46cfd75
commit 8920c5f2a1
8 changed files with 252 additions and 0 deletions

View File

@ -897,6 +897,8 @@
vfs
..
vm
stack
..
..
vmm
..

View File

@ -17,4 +17,9 @@ ATF_TESTS_SH+= mmap_map_32bit_test
PROGS+= mmap_map_32bit_helper
.endif
SUBDIR= soxstack
TESTS_SUBDIRS+= stack
SUBDIR_DEPENDS_stack=soxstack
.include <bsd.test.mk>

View File

@ -0,0 +1,17 @@
# $FreeBSD$
SHLIB= soxstack
SHLIB_NAME= libsoxstack.so
SHLIB_MAJOR= 1
WITHOUT_STATIC=
WITHOUT_PROFILE=
WITHOUT_PIC=
SRCS= soxstack.c
LDFLAGS+= -Wl,-z,execstack
LIBADD+= procstat
LIBDIR= ${TESTSBASE}/sys/vm/stack
.include <bsd.lib.mk>

View File

@ -0,0 +1,51 @@
/*-
* Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <assert.h>
#include <libprocstat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int checkstack(void);
#define _STACK_FLAG_GROWS KVME_FLAG_GROWS_UP | KVME_FLAG_GROWS_DOWN
int
checkstack(void)
{
struct kinfo_vmentry *freep, *kve;
struct kinfo_proc *p;
struct procstat *prstat;
uint64_t stack;
int i, cnt;
prstat = procstat_open_sysctl();
assert(prstat != NULL);
p = procstat_getprocs(prstat, KERN_PROC_PID, getpid(), &cnt);
assert(p != NULL);
freep = procstat_getvmmap(prstat, p, &cnt);
assert(freep != NULL);
stack = (uint64_t)&i;
for (i = 0; i < cnt; i++) {
kve = &freep[i];
if (stack < kve->kve_start || stack > kve->kve_end)
continue;
if ((kve->kve_flags & _STACK_FLAG_GROWS) != 0 &&
(kve->kve_protection & KVME_PROT_EXEC) != 0)
stack = 0;
break;
}
free(freep);
procstat_freeprocs(prstat, p);
procstat_close(prstat);
return (stack != 0);
}

View File

@ -0,0 +1,15 @@
# $FreeBSD$
PACKAGE= tests
TESTSDIR= ${TESTSBASE}/sys/vm/stack
ATF_TESTS_C+= stack_dt_need_exec_test
ATF_TESTS_C+= stack_dlopen_exec_test
ATF_TESTS_C+= stack_mprotect_exec_test
LDFLAGS.stack_dt_need_exec_test+= -Wl,-rpath,${TESTSDIR} -L${.OBJDIR:H}/soxstack
LDADD.stack_dt_need_exec_test+= -lsoxstack
LDFLAGS.stack_dlopen_exec_test+= -Wl,-rpath,${TESTSDIR}
.include <bsd.test.mk>

View File

@ -0,0 +1,64 @@
/*-
* Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/systm.h>
#include <vm/vm_param.h>
#include <atf-c.h>
#include <dlfcn.h>
static int jumpstack0(void) __noinline;
static int jumpstack1(void) __noinline;
static int (*socheckstack)(void) = NULL;
static int
checkstack(void)
{
void *fh;
if (socheckstack == NULL) {
fh = dlopen("libsoxstack.so", RTLD_LAZY);
ATF_REQUIRE(fh != NULL);
socheckstack = dlsym(fh, "checkstack");
ATF_REQUIRE(socheckstack != NULL);
}
return (socheckstack());
}
static int
jumpstack0(void)
{
char stack[SGROWSIZ];
explicit_bzero(stack, sizeof(stack));
return (checkstack());
}
static int
jumpstack1(void)
{
char stack[SGROWSIZ * 2];
explicit_bzero(stack, sizeof(stack));
return (checkstack());
}
ATF_TC_WITHOUT_HEAD(dlopen_test);
ATF_TC_BODY(dlopen_test, tc)
{
ATF_REQUIRE(jumpstack0() == 0);
ATF_REQUIRE(jumpstack1() == 0);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, dlopen_test);
return (atf_no_error());
}

View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <sys/systm.h>
#include <vm/vm_param.h>
#include <atf-c.h>
extern int checkstack(void);
static int jumpstack0(void) __noinline;
static int jumpstack1(void) __noinline;
static int
jumpstack0(void)
{
char stack[SGROWSIZ];
explicit_bzero(stack, sizeof(stack));
return (checkstack());
}
static int
jumpstack1(void)
{
char stack[SGROWSIZ * 2];
explicit_bzero(stack, sizeof(stack));
return (checkstack());
}
ATF_TC_WITHOUT_HEAD(dt_need_test);
ATF_TC_BODY(dt_need_test, tc)
{
ATF_REQUIRE(jumpstack0() == 0);
ATF_REQUIRE(jumpstack1() == 0);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, dt_need_test);
return (atf_no_error());
}

View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 2023 Dmitry Chagin <dchagin@FreeBSD.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*
* PR: 272585
* Test provided by John F. Carr
*/
#include <sys/systm.h>
#include <sys/mman.h>
#include <vm/vm_param.h>
#include <atf-c.h>
#include <unistd.h>
ATF_TC_WITHOUT_HEAD(mprotect_exec_test);
ATF_TC_BODY(mprotect_exec_test, tc)
{
long pagesize;
char *addr, *guard;
size_t alloc_size;
pagesize = sysconf(_SC_PAGESIZE);
ATF_REQUIRE(pagesize > 0);
alloc_size = SGROWSIZ * 2;
addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
MAP_STACK | MAP_PRIVATE | MAP_ANON, -1, 0);
ATF_REQUIRE(addr != MAP_FAILED);
/*
* Change prot of the last page in the mmaped stack area.
*/
guard = addr + alloc_size - SGROWSIZ;
ATF_REQUIRE(mprotect(guard, pagesize, PROT_NONE) == 0);
((volatile char *)guard)[-1];
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, mprotect_exec_test);
return (atf_no_error());
}