1 // Copyright 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // This file defines the sandbox2::Regs class stores context of a process 16 // during ptrace stop events 17 18 #ifndef SANDBOXED_API_SANDBOX2_REGS_H_ 19 #define SANDBOXED_API_SANDBOX2_REGS_H_ 20 21 #include <sys/types.h> 22 23 #include <cstdint> 24 25 #include "absl/status/status.h" 26 #include "sandboxed_api/config.h" 27 #include "sandboxed_api/sandbox2/syscall.h" 28 29 namespace sandbox2 { 30 31 // Helper class to get and modify running processes registers. Uses ptrace and 32 // assumes the process is already attached. 33 class Regs { 34 public: Regs(pid_t pid)35 explicit Regs(pid_t pid) : pid_(pid) {} 36 37 // Copies register values from the process 38 absl::Status Fetch(); 39 40 // Copies register values to the process 41 absl::Status Store(); 42 43 // Causes the process to skip current syscall and return given value instead 44 absl::Status SkipSyscallReturnValue(uintptr_t value); 45 46 // Converts raw register values obtained on syscall entry to syscall info 47 Syscall ToSyscall(sapi::cpu::Architecture syscall_arch) const; 48 49 // Returns the content of the register that holds a syscall's return value 50 int64_t GetReturnValue(sapi::cpu::Architecture syscall_arch) const; 51 pid()52 pid_t pid() const { return pid_; } 53 54 private: 55 friend class StackTracePeer; 56 57 struct PtraceRegisters { 58 #if defined(SAPI_X86_64) 59 uint64_t r15; 60 uint64_t r14; 61 uint64_t r13; 62 uint64_t r12; 63 uint64_t rbp; 64 uint64_t rbx; 65 uint64_t r11; 66 uint64_t r10; 67 uint64_t r9; 68 uint64_t r8; 69 uint64_t rax; 70 uint64_t rcx; 71 uint64_t rdx; 72 uint64_t rsi; 73 uint64_t rdi; 74 uint64_t orig_rax; 75 uint64_t rip; 76 uint64_t cs; 77 uint64_t eflags; 78 uint64_t rsp; 79 uint64_t ss; 80 uint64_t fs_base; 81 uint64_t gs_base; 82 uint64_t ds; 83 uint64_t es; 84 uint64_t fs; 85 uint64_t gs; 86 #elif defined(SAPI_PPC64_LE) 87 uint64_t gpr[32]; 88 uint64_t nip; 89 uint64_t msr; 90 uint64_t orig_gpr3; 91 uint64_t ctr; 92 uint64_t link; 93 uint64_t xer; 94 uint64_t ccr; 95 uint64_t softe; 96 uint64_t trap; 97 uint64_t dar; 98 uint64_t dsisr; 99 uint64_t result; 100 // elf.h's ELF_NGREG says it's 48 registers, so kernel fills it in with some 101 // zeroes. 102 uint64_t zero0; 103 uint64_t zero1; 104 uint64_t zero2; 105 uint64_t zero3; 106 #elif defined(SAPI_ARM64) 107 uint64_t regs[31]; 108 uint64_t sp; 109 uint64_t pc; 110 uint64_t pstate; 111 #elif defined(SAPI_ARM) 112 uint32_t regs[15]; 113 uint32_t pc; 114 uint32_t cpsr; 115 uint32_t orig_x0; 116 #else 117 static_assert(false, "Host CPU architecture not supported, see config.h"); 118 #endif 119 }; 120 121 // PID for which registers are fetched/stored 122 pid_t pid_ = 0; 123 124 // Registers fetched with ptrace(PR_GETREGS/GETREGSET, pid). 125 PtraceRegisters user_regs_ = {}; 126 127 // On AArch64, obtaining the syscall number needs a specific call to ptrace() 128 int syscall_number_ = 0; 129 }; 130 131 } // namespace sandbox2 132 133 #endif // SANDBOXED_API_SANDBOX2_REGS_H_ 134