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 #include "sandboxed_api/sandbox2/violation.pb.h" 29 30 namespace sandbox2 { 31 32 // Helper class to get and modify running processes registers. Uses ptrace and 33 // assumes the process is already attached. 34 class Regs { 35 public: Regs(pid_t pid)36 explicit Regs(pid_t pid) : pid_(pid) {} 37 38 // Copies register values from the process 39 absl::Status Fetch(); 40 41 // Copies register values to the process 42 absl::Status Store(); 43 44 // Causes the process to skip current syscall and return given value instead 45 absl::Status SkipSyscallReturnValue(uintptr_t value); 46 47 // Converts raw register values obtained on syscall entry to syscall info 48 Syscall ToSyscall(sapi::cpu::Architecture syscall_arch) const; 49 50 // Returns the content of the register that holds a syscall's return value 51 int64_t GetReturnValue(sapi::cpu::Architecture syscall_arch) const; 52 pid()53 pid_t pid() const { return pid_; } 54 55 // Stores register values in a protobuf structure. 56 void StoreRegisterValuesInProtobuf(RegisterValues* values) const; 57 58 private: 59 friend class StackTracePeer; 60 61 struct PtraceRegisters { 62 #if defined(SAPI_X86_64) 63 uint64_t r15; 64 uint64_t r14; 65 uint64_t r13; 66 uint64_t r12; 67 uint64_t rbp; 68 uint64_t rbx; 69 uint64_t r11; 70 uint64_t r10; 71 uint64_t r9; 72 uint64_t r8; 73 uint64_t rax; 74 uint64_t rcx; 75 uint64_t rdx; 76 uint64_t rsi; 77 uint64_t rdi; 78 uint64_t orig_rax; 79 uint64_t rip; 80 uint64_t cs; 81 uint64_t eflags; 82 uint64_t rsp; 83 uint64_t ss; 84 uint64_t fs_base; 85 uint64_t gs_base; 86 uint64_t ds; 87 uint64_t es; 88 uint64_t fs; 89 uint64_t gs; 90 #elif defined(SAPI_PPC64_LE) 91 uint64_t gpr[32]; 92 uint64_t nip; 93 uint64_t msr; 94 uint64_t orig_gpr3; 95 uint64_t ctr; 96 uint64_t link; 97 uint64_t xer; 98 uint64_t ccr; 99 uint64_t softe; 100 uint64_t trap; 101 uint64_t dar; 102 uint64_t dsisr; 103 uint64_t result; 104 // elf.h's ELF_NGREG says it's 48 registers, so kernel fills it in with some 105 // zeroes. 106 uint64_t zero0; 107 uint64_t zero1; 108 uint64_t zero2; 109 uint64_t zero3; 110 #elif defined(SAPI_ARM64) 111 uint64_t regs[31]; 112 uint64_t sp; 113 uint64_t pc; 114 uint64_t pstate; 115 #elif defined(SAPI_ARM) 116 uint32_t regs[15]; 117 uint32_t pc; 118 uint32_t cpsr; 119 uint32_t orig_x0; 120 #else 121 static_assert(false, "Host CPU architecture not supported, see config.h"); 122 #endif 123 }; 124 125 // PID for which registers are fetched/stored 126 pid_t pid_ = 0; 127 128 // Registers fetched with ptrace(PR_GETREGS/GETREGSET, pid). 129 PtraceRegisters user_regs_ = {}; 130 131 // On AArch64, obtaining the syscall number needs a specific call to ptrace() 132 int syscall_number_ = 0; 133 }; 134 135 } // namespace sandbox2 136 137 #endif // SANDBOXED_API_SANDBOX2_REGS_H_ 138