1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <jni.h> 18 #include <gtest/gtest.h> 19 #include <android/log.h> 20 21 #include <errno.h> 22 #include <sys/ptrace.h> 23 #include <sys/types.h> 24 #include <sys/uio.h> 25 #include <sys/wait.h> 26 #include <unistd.h> 27 28 #include <functional> 29 #include <vector> 30 31 #define LOG_TAG "Cts-DebugTest" 32 33 // Used by child processes only 34 #define assert_or_exit(x) \ 35 do { \ 36 if(x) break; \ 37 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Assertion " #x " failed. errno(%d): %s", \ 38 errno, strerror(errno)); \ 39 _exit(1); \ 40 } while (0) 41 42 static void parent(pid_t child) { 43 int status; 44 int wpid = waitpid(child, &status, 0); 45 ASSERT_EQ(child, wpid); 46 ASSERT_TRUE(WIFEXITED(status)); 47 ASSERT_EQ(0, WEXITSTATUS(status)); 48 } 49 50 static void run_test(const std::function<void(pid_t)> &test) { 51 pid_t pid = fork(); 52 ASSERT_NE(-1, pid) << "fork() failed with " << strerror(errno); 53 if (pid != 0) { 54 parent(pid); 55 } else { 56 // child 57 test(getppid()); 58 _exit(0); 59 } 60 } 61 62 static void ptraceAttach(pid_t parent) { 63 assert_or_exit(ptrace(PTRACE_ATTACH, parent, nullptr, nullptr) == 0); 64 int status; 65 assert_or_exit(waitpid(parent, &status, __WALL) == parent); 66 assert_or_exit(WIFSTOPPED(status)); 67 assert_or_exit(WSTOPSIG(status) == SIGSTOP); 68 69 assert_or_exit(ptrace(PTRACE_DETACH, parent, nullptr, nullptr) == 0); 70 } 71 72 TEST(DebugTest, ptraceAttach) { 73 run_test(ptraceAttach); 74 } 75 76 static void processVmReadv(pid_t parent, const std::vector<long *> &addresses) { 77 long destination; 78 iovec local = { &destination, sizeof destination }; 79 80 for (long *address : addresses) { 81 // Since we are forked, the address will be valid in the remote process as well. 82 iovec remote = { address, sizeof *address }; 83 __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%s About to read %p\n", __func__, 84 address); 85 assert_or_exit(process_vm_readv(parent, &local, 1, &remote, 1, 0) == sizeof destination); 86 87 // Compare the data with the contents of our memory. 88 assert_or_exit(destination == *address); 89 } 90 } 91 92 static long global_variable = 0x47474747; 93 // public static native boolean processVmReadv(); 94 TEST(DebugTest, processVmReadv) { 95 long stack_variable = 0x42424242; 96 // This runs the test with a selection of different kinds of addresses and 97 // makes sure the child process (simulating a debugger) can read them. 98 run_test([&](pid_t parent) { 99 processVmReadv(parent, std::vector<long *>{ 100 &global_variable, &stack_variable, 101 reinterpret_cast<long *>(&processVmReadv)}); 102 }); 103 } 104 105 // public static native boolean processVmReadvNullptr(); 106 TEST(DebugTest, processVmReadvNullptr) { 107 // Make sure reading unallocated memory behaves reasonably. 108 run_test([](pid_t parent) { 109 long destination; 110 iovec local = {&destination, sizeof destination}; 111 iovec remote = {nullptr, sizeof(long)}; 112 113 assert_or_exit(process_vm_readv(parent, &local, 1, &remote, 1, 0) == -1); 114 assert_or_exit(errno == EFAULT); 115 }); 116 } 117