This tests both the original issue of mprotect reintroducing COW pages to Xenomai processes as well as the recently fixed zero page corruption.
Signed-off-by: Jan Kiszka <[email protected]> --- src/testsuite/regression/native/Makefile.am | 2 +- src/testsuite/regression/native/Makefile.in | 16 +++- src/testsuite/regression/native/mprotect.c | 128 +++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 src/testsuite/regression/native/mprotect.c diff --git a/src/testsuite/regression/native/Makefile.am b/src/testsuite/regression/native/Makefile.am index ce53834..afd2f43 100644 --- a/src/testsuite/regression/native/Makefile.am +++ b/src/testsuite/regression/native/Makefile.am @@ -2,7 +2,7 @@ tstdir = @XENO_TEST_DIR@/regression/native noinst_HEADERS = check.h -tst_PROGRAMS = leaks tsc heap sigdebug +tst_PROGRAMS = leaks tsc heap sigdebug mprotect CPPFLAGS = $(XENO_USER_CFLAGS) \ -I$(top_srcdir)/include diff --git a/src/testsuite/regression/native/Makefile.in b/src/testsuite/regression/native/Makefile.in index 3d5a0ce..b2ae93a 100644 --- a/src/testsuite/regression/native/Makefile.in +++ b/src/testsuite/regression/native/Makefile.in @@ -37,7 +37,7 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ tst_PROGRAMS = leaks$(EXEEXT) tsc$(EXEEXT) heap$(EXEEXT) \ - sigdebug$(EXEEXT) + sigdebug$(EXEEXT) mprotect$(EXEEXT) subdir = src/testsuite/regression/native DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in @@ -70,6 +70,12 @@ leaks_LDADD = $(LDADD) leaks_DEPENDENCIES = ../../../skins/native/libnative.la \ ../../../skins/rtdm/librtdm.la \ ../../../skins/common/libxenomai.la +mprotect_SOURCES = mprotect.c +mprotect_OBJECTS = mprotect.$(OBJEXT) +mprotect_LDADD = $(LDADD) +mprotect_DEPENDENCIES = ../../../skins/native/libnative.la \ + ../../../skins/rtdm/librtdm.la \ + ../../../skins/common/libxenomai.la sigdebug_SOURCES = sigdebug.c sigdebug_OBJECTS = sigdebug.$(OBJEXT) sigdebug_LDADD = $(LDADD) @@ -95,8 +101,8 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = heap.c leaks.c sigdebug.c tsc.c -DIST_SOURCES = heap.c leaks.c sigdebug.c tsc.c +SOURCES = heap.c leaks.c mprotect.c sigdebug.c tsc.c +DIST_SOURCES = heap.c leaks.c mprotect.c sigdebug.c tsc.c HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags @@ -348,6 +354,9 @@ heap$(EXEEXT): $(heap_OBJECTS) $(heap_DEPENDENCIES) leaks$(EXEEXT): $(leaks_OBJECTS) $(leaks_DEPENDENCIES) @rm -f leaks$(EXEEXT) $(LINK) $(leaks_OBJECTS) $(leaks_LDADD) $(LIBS) +mprotect$(EXEEXT): $(mprotect_OBJECTS) $(mprotect_DEPENDENCIES) + @rm -f mprotect$(EXEEXT) + $(LINK) $(mprotect_OBJECTS) $(mprotect_LDADD) $(LIBS) sigdebug$(EXEEXT): $(sigdebug_OBJECTS) $(sigdebug_DEPENDENCIES) @rm -f sigdebug$(EXEEXT) $(LINK) $(sigdebug_OBJECTS) $(sigdebug_LDADD) $(LIBS) @@ -363,6 +372,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/leaks.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mprotect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigdebug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsc.Po@am__quote@ diff --git a/src/testsuite/regression/native/mprotect.c b/src/testsuite/regression/native/mprotect.c new file mode 100644 index 0000000..7d66e34 --- /dev/null +++ b/src/testsuite/regression/native/mprotect.c @@ -0,0 +1,128 @@ +/* + * Test if implicit pinning of memory via mprotect works. + * + * Copyright (C) Jan Kiszka <[email protected]> + * + * Released under the terms of GPLv2. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <signal.h> +#include <sys/mman.h> +#include <rtdk.h> +#include <native/task.h> + +#define MEMSIZE 0x10000 + +static void check_inner(const char *fn, int line, const char *msg, + int status, int expected) +{ + if (status == expected) + return; + + rt_task_set_mode(T_WARNSW, 0, NULL); + rt_print_flush_buffers(); + fprintf(stderr, "FAILURE %s:%d: %s returned %d instead of %d - %s\n", + fn, line, msg, status, expected, strerror(-status)); + exit(EXIT_FAILURE); +} + +#define check_no_error(msg, status) ({ \ + int __status = status; \ + check_inner(__FUNCTION__, __LINE__, msg, \ + __status < 0 ? __status : 0, 0); \ + __status; \ +}) + +static void check_value_inner(const char *fn, int line, const char *msg, + int value, int expected) +{ + if (value == expected) + return; + + rt_task_set_mode(T_WARNSW, 0, NULL); + rt_print_flush_buffers(); + fprintf(stderr, + "FAILURE %s:%d: %s returned %u instead of %u\n", + fn, line, msg, value, expected); + exit(EXIT_FAILURE); +} + +#define check_value(msg, value, expected) do { \ + int __value = value; \ + check_value_inner(__FUNCTION__, __LINE__, msg, __value, \ + expected); \ +} while (0) + +void sigdebug_handler(int sig, siginfo_t *si, void *context) +{ + unsigned int reason = si->si_value.sival_int; + + rt_print_flush_buffers(); + fprintf(stderr, "FAILURE: sigdebug_handler triggered, reason %d\n", + reason); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + unsigned char *zero_mem, *test1_mem, *test2_mem; + RT_TASK main_task; + struct sigaction sa; + int err; + + rt_print_auto_init(1); + + errno = 0; + zero_mem = mmap(0, MEMSIZE, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + check_no_error("mmap", -errno); + test1_mem = mmap(0, MEMSIZE, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + check_no_error("mmap", -errno); + + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = sigdebug_handler; + sa.sa_flags = SA_SIGINFO; + sigaction(SIGDEBUG, &sa, NULL); + + mlockall(MCL_CURRENT | MCL_FUTURE); + + err = rt_task_shadow(&main_task, "main_task", 1, T_WARNSW); + check_no_error("rt_task_shadow", err); + + rt_printf("memory read\n"); + check_value("read mem", test1_mem[0], 0); + + rt_task_set_mode(T_WARNSW, 0, NULL); + errno = 0; + test2_mem = mmap(0, MEMSIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + check_no_error("mmap", -errno); + mprotect(test2_mem, MEMSIZE, PROT_READ | PROT_WRITE | PROT_EXEC); + check_no_error("mprotect", -errno); + + rt_task_sleep(0); + rt_task_set_mode(0, T_WARNSW, NULL); + + rt_printf("memory write after exec enable\n"); + test2_mem[0] = 0xff; + + rt_task_set_mode(T_WARNSW, 0, NULL); + err = mprotect(test1_mem, MEMSIZE, PROT_READ | PROT_WRITE); + check_no_error("mprotect", err); + + rt_task_sleep(0); + rt_task_set_mode(0, T_WARNSW, NULL); + + rt_printf("memory write after write enable\n"); + test1_mem[0] = 0xff; + check_value("read zero", zero_mem[0], 0); + + rt_task_set_mode(T_WARNSW, 0, NULL); + rt_print_flush_buffers(); + fprintf(stderr, "Test OK\n"); + + return 0; +} -- 1.7.3.4 _______________________________________________ Xenomai-core mailing list [email protected] https://mail.gna.org/listinfo/xenomai-core
