diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-07-13 23:50:56 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2018-03-15 10:52:37 +0000 |
commit | 71aa8da50fb2f1fb1d0e8ea163f5dfcf17547ac3 (patch) | |
tree | c6ab9a1c5d2722e2196631c63b7180017e69e3d3 | |
parent | 8b246495bb6c892a3bfd2ed0ce146e06e654706c (diff) |
igt/gem_mmap_gtt: Simulate gdb inspecting a GTT mmap using ptrace()
gdb uses ptrace() to peek and poke bytes of the target's address space.
The kernel must implement an vm_ops->access() handler or else gdb will
be unable to inspect the pointer and report it as out-of-bounds. Worse
than useless as it causes immediate suspicion of the valid GTT pointer.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | tests/gem_mmap_gtt.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/tests/gem_mmap_gtt.c b/tests/gem_mmap_gtt.c index 6a332b25..a3259e64 100644 --- a/tests/gem_mmap_gtt.c +++ b/tests/gem_mmap_gtt.c @@ -35,6 +35,8 @@ #include <errno.h> #include <sys/stat.h> #include <sys/ioctl.h> +#include <sys/ptrace.h> +#include <sys/wait.h> #include "drm.h" #include "igt.h" @@ -309,6 +311,81 @@ test_write_gtt(int fd) munmap(src, OBJECT_SIZE); } +static void *memchr_inv(const void *s, int c, size_t n) +{ + const uint8_t *us = s; + const uint8_t uc = c; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" + while (n--) { + if (*us != uc) + return (void *) us; + us++; + } +#pragma GCC diagnostic pop + + return NULL; +} + +static void +test_ptrace(int fd) +{ + long AA, CC; + long *gtt, *copy; + uint32_t bo; + pid_t pid; + + memset(&AA, 0xaa, sizeof(AA)); + memset(&CC, 0x55, sizeof(CC)); + + copy = malloc(OBJECT_SIZE); + memset(copy, AA, OBJECT_SIZE); + + bo = gem_create(fd, OBJECT_SIZE); + gtt = mmap_bo(fd, bo); + memset(gtt, CC, OBJECT_SIZE); + gem_close(fd, bo); + + igt_assert(!memchr_inv(gtt, CC, OBJECT_SIZE)); + igt_assert(!memchr_inv(copy, AA, OBJECT_SIZE)); + + switch ((pid = fork())) { + case -1: + igt_assert(pid != -1); + break; + + case 0: + ptrace(PTRACE_TRACEME, 0, NULL, NULL); + raise(SIGSTOP); + raise(SIGKILL); + exit(0); + break; + + default: + /* Wait for the child to ready themselves */ + wait(NULL); + + ptrace(PTRACE_ATTACH, pid, NULL, NULL); + for (int i = 0; i < OBJECT_SIZE/sizeof(long); i++) { + copy[i] = ptrace(PTRACE_PEEKDATA, pid, gtt+i, NULL); + ptrace(PTRACE_POKEDATA, pid, gtt + i, AA); + } + ptrace(PTRACE_DETACH, pid, NULL, NULL); + + /* Wakeup the child for it to exit */ + kill(SIGCONT, pid); + break; + } + + /* The contents of the two buffers should now be swapped */ + igt_assert(!memchr_inv(gtt, AA, OBJECT_SIZE)); + igt_assert(!memchr_inv(copy, CC, OBJECT_SIZE)); + + munmap(gtt, OBJECT_SIZE); + free(copy); +} + static void test_coherency(int fd) { @@ -773,6 +850,8 @@ igt_main test_write(fd); igt_subtest("basic-write-gtt") test_write_gtt(fd); + igt_subtest("ptrace") + test_ptrace(fd); igt_subtest("coherency") test_coherency(fd); igt_subtest("clflush") |