diff options
Diffstat (limited to 'libmemunreachable/PtracerThread.cpp')
-rw-r--r-- | libmemunreachable/PtracerThread.cpp | 155 |
1 files changed, 0 insertions, 155 deletions
diff --git a/libmemunreachable/PtracerThread.cpp b/libmemunreachable/PtracerThread.cpp deleted file mode 100644 index d2fca49f2..000000000 --- a/libmemunreachable/PtracerThread.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <pthread.h> -#include <sched.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/prctl.h> -#include <sys/syscall.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -#include "android-base/macros.h" - -#include "PtracerThread.h" -#include "log.h" - -namespace android { - -class Stack { - public: - explicit Stack(size_t size) : size_(size) { - int prot = PROT_READ | PROT_WRITE; - int flags = MAP_PRIVATE | MAP_ANONYMOUS; - page_size_ = sysconf(_SC_PAGE_SIZE); - size_ += page_size_ * 2; // guard pages - base_ = mmap(NULL, size_, prot, flags, -1, 0); - if (base_ == MAP_FAILED) { - base_ = NULL; - size_ = 0; - return; - } - prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, base_, size_, "libmemunreachable stack"); - mprotect(base_, page_size_, PROT_NONE); - mprotect(top(), page_size_, PROT_NONE); - }; - ~Stack() { munmap(base_, size_); }; - void* top() { - return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(base_) + size_ - page_size_); - }; - - private: - DISALLOW_COPY_AND_ASSIGN(Stack); - - void* base_; - size_t size_; - size_t page_size_; -}; - -PtracerThread::PtracerThread(const std::function<int()>& func) : child_pid_(0) { - stack_ = std::make_unique<Stack>(PTHREAD_STACK_MIN); - if (stack_->top() == nullptr) { - MEM_LOG_ALWAYS_FATAL("failed to mmap child stack: %s", strerror(errno)); - } - - func_ = std::function<int()>{[&, func]() -> int { - // In the child thread, lock and unlock the mutex to wait for the parent - // to finish setting up for the child thread - std::unique_lock<std::mutex> lk(m_); - lk.unlock(); - _exit(func()); - }}; -} - -PtracerThread::~PtracerThread() { - Kill(); - Join(); - ClearTracer(); - stack_ = nullptr; -} - -bool PtracerThread::Start() { - std::unique_lock<std::mutex> lk(m_); - - // Convert from void(*)(void*) to lambda with captures - auto proxy = [](void* arg) -> int { - prctl(PR_SET_NAME, "libmemunreachable ptrace thread"); - return (*reinterpret_cast<std::function<int()>*>(arg))(); - }; - - // See README.md for why we create the child process this way - child_pid_ = clone(proxy, stack_->top(), CLONE_VM | CLONE_FS | CLONE_FILES /*|CLONE_UNTRACED*/, - reinterpret_cast<void*>(&func_)); - if (child_pid_ < 0) { - MEM_ALOGE("failed to clone child: %s", strerror(errno)); - return false; - } - - SetTracer(child_pid_); - - lk.unlock(); - - return true; -} - -int PtracerThread::Join() { - if (child_pid_ == -1) { - return -1; - } - int status; - int ret = TEMP_FAILURE_RETRY(waitpid(child_pid_, &status, __WALL)); - if (ret < 0) { - MEM_ALOGE("waitpid %d failed: %s", child_pid_, strerror(errno)); - return -1; - } - - child_pid_ = -1; - - if (WIFEXITED(status)) { - return WEXITSTATUS(status); - } else if (WIFSIGNALED(status)) { - return -WTERMSIG(status); - } else { - MEM_ALOGE("unexpected status %x", status); - return -1; - } -} - -void PtracerThread::Kill() { - if (child_pid_ == -1) { - return; - } - - syscall(SYS_tkill, child_pid_, SIGKILL); -} - -void PtracerThread::SetTracer(pid_t tracer_pid) { - prctl(PR_SET_PTRACER, tracer_pid); -} - -void PtracerThread::ClearTracer() { - prctl(PR_SET_PTRACER, 0); -} - -} // namespace android |