Testcase tried to copy page size area starting at &exec_func.
This results in crash on powerpc, because &exec_func is too close
to end of page and subsequent page is not mapped:

 10000000-10010000 r-xp 00000000 fd:00 402855 mprotect04
 10010000-10020000 rw-p 00000000 fd:00 402855 mprotect04
 806a410000-806a440000 r-xp 00000000 fd:00 2097827 /lib64/ld-2.12.so
where &exec_func == 0x100199c0, and page_size == 65536.

It's also worth noting, that function ptr does not reside in .text,
but in .opd section. That shouldn't matter for this testcase as long
as it doesn't try to copy non-existent pages.

This patch is changing copy function to try copy 2 whole aligned pages.
Both pages are checked to be present in memory before memcpy is
attempted. First is the page which contains &exec_func, and 2nd is the
subsequent page - for the case &exec_func is too close to page boundary.

Signed-off-by: Jan Stancek <jstan...@redhat.com>
---
 testcases/kernel/syscalls/mprotect/mprotect04.c | 61 +++++++++++++++++++++----
 1 file changed, 52 insertions(+), 9 deletions(-)

diff --git a/testcases/kernel/syscalls/mprotect/mprotect04.c 
b/testcases/kernel/syscalls/mprotect/mprotect04.c
index 8a4a72ad69f2..23aecbd856f4 100644
--- a/testcases/kernel/syscalls/mprotect/mprotect04.c
+++ b/testcases/kernel/syscalls/mprotect/mprotect04.c
@@ -54,6 +54,7 @@ int TST_TOTAL = ARRAY_SIZE(testfunc);
 
 static volatile int sig_caught;
 static sigjmp_buf env;
+static int copy_sz;
 
 int main(int ac, char **av)
 {
@@ -83,7 +84,9 @@ static void sighandler(int sig)
 
 static void setup(void)
 {
+       tst_tmpdir();
        tst_sig(NOFORK, sighandler, cleanup);
+       copy_sz = getpagesize() * 2;
 
        TEST_PAUSE;
 }
@@ -158,32 +161,71 @@ static void exec_func(void)
        return;
 }
 
-static void *get_func(void *mem)
+static int page_present(void *p)
 {
-       memcpy(mem, exec_func, getpagesize());
+       int fd;
+
+       fd = SAFE_OPEN(cleanup, "page_present", O_WRONLY|O_CREAT, 0644);
+       TEST(write(fd, p, 1));
+       SAFE_CLOSE(cleanup, fd);
+
+       if (TEST_RETURN >= 0)
+               return 1;
+
+       if (TEST_ERRNO != EFAULT)
+               tst_brkm(TBROK | TTERRNO, cleanup, "page_present write");
 
-       return mem;
+       return 0;
+}
+
+/*
+ * Copy page where &exec_func resides. Also try to copy subsequent page
+ * in case exec_func is close to page boundary.
+ */
+static void *get_func(void *mem)
+{
+       uintptr_t page_sz = getpagesize();
+       uintptr_t page_mask = ~(page_sz - 1);
+       uintptr_t func_page_offset = (uintptr_t)&exec_func & (page_sz - 1);
+       void *func_copy_start = mem + func_page_offset;
+       void *page_to_copy = (void *)((uintptr_t)&exec_func & page_mask);
+
+       /* copy 1st page, if it's not present something is wrong */
+       if (!page_present(page_to_copy)) {
+               tst_resm(TINFO, "exec_func: %p, page_to_copy: %p\n",
+                       &exec_func, page_to_copy);
+               tst_brkm(TBROK, cleanup, "page_to_copy not present\n");
+       }
+       memcpy(mem, page_to_copy, page_sz);
+
+       /* copy 2nd page if possible */
+       mem += page_sz;
+       page_to_copy += page_sz;
+       if (page_present(page_to_copy))
+               memcpy(mem, page_to_copy, page_sz);
+       else
+               memset(mem, 0, page_sz);
+
+       /* return pointer to area where copy of exec_func resides */
+       return func_copy_start;
 }
 
 #endif
 
 static void testfunc_protexec(void)
 {
-       int page_sz;
        void (*func)(void);
        void *p;
 
        sig_caught = 0;
 
-       page_sz = getpagesize();
-
-       p = SAFE_MMAP(cleanup, 0, page_sz, PROT_READ | PROT_WRITE,
+       p = SAFE_MMAP(cleanup, 0, copy_sz, PROT_READ | PROT_WRITE,
                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 
        func = get_func(p);
 
        /* Change the protection to PROT_EXEC. */
-       TEST(mprotect(p, page_sz, PROT_EXEC));
+       TEST(mprotect(p, copy_sz, PROT_EXEC));
 
        if (TEST_RETURN == -1) {
                tst_resm(TFAIL | TTERRNO, "mprotect failed");
@@ -205,9 +247,10 @@ static void testfunc_protexec(void)
                }
        }
 
-       SAFE_MUNMAP(cleanup, p, page_sz);
+       SAFE_MUNMAP(cleanup, p, copy_sz);
 }
 
 static void cleanup(void)
 {
+       tst_rmdir();
 }
-- 
1.8.3.1


------------------------------------------------------------------------------
Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
Get real-time metrics from all of your servers, apps and tools
in one place.
SourceForge users - Click here to start your Free Trial of Datadog now!
http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

Reply via email to