diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile index 48d47c06a..9c2c5814f 100644 --- a/test/zdtm/live/static/Makefile +++ b/test/zdtm/live/static/Makefile @@ -98,6 +98,7 @@ TST_NOFILE = \ sigaltstack \ sk-netlink \ mem-touch \ + grow_map \ # jobctl00 \ TST_FILE = \ diff --git a/test/zdtm/live/static/grow_map.c b/test/zdtm/live/static/grow_map.c new file mode 100644 index 000000000..7ce0eb809 --- /dev/null +++ b/test/zdtm/live/static/grow_map.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#include "zdtmtst.h" + +const char *test_doc = "Check that VMA-s with MAP_GROWSDOWN are restored correctly"; +const char *test_author = "Andrew Vagin "; + +int main(int argc, char **argv) +{ + char *start_addr, *fake_grow_down, *test_addr, *grow_down; + test_init(argc, argv); + + start_addr = mmap(NULL, PAGE_SIZE * 10, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (start_addr == MAP_FAILED) { + err("Can't mal a new region"); + return 1; + } + munmap(start_addr, PAGE_SIZE * 10); + + fake_grow_down = mmap(start_addr + PAGE_SIZE * 5, PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0); + if (fake_grow_down == MAP_FAILED) { + err("Can't mal a new region"); + return 1; + } + + fake_grow_down[0] = 'c'; + *(fake_grow_down - 1) = 'b'; + + /* overlap the guard page of fake_grow_down */ + test_addr = mmap(start_addr + PAGE_SIZE * 3, PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (test_addr == MAP_FAILED) { + err("Can't mal a new region"); + return 1; + } + + grow_down = mmap(start_addr + PAGE_SIZE * 2, PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED | MAP_GROWSDOWN, -1, 0); + if (grow_down == MAP_FAILED) { + err("Can't mal a new region"); + return 1; + } + + test_daemon(); + test_waitsig(); + + munmap(test_addr, PAGE_SIZE); + if (fake_grow_down[0] != 'c' || *(fake_grow_down - 1) != 'b') { + fail("%c %c\n", fake_grow_down[0], *(fake_grow_down - 1)); + return 1; + } + + grow_down[0] = 'z'; + *(grow_down - 1) = 'x'; + + pass(); + + return 0; +}