1 /*
2  * Copyright (C) 2016 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 <errno.h>
18 #include <fcntl.h>
19 #include <sys/mman.h>
20 #include <sys/ptrace.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/uio.h>
24 #include <unistd.h>
25 
26 #include <algorithm>
27 #include <memory>
28 
29 #include <android-base/unique_fd.h>
30 
31 #include "Memory.h"
32 
ReadString(uint64_t addr,std::string * string,uint64_t max_read)33 bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) {
34   string->clear();
35   uint64_t bytes_read = 0;
36   while (bytes_read < max_read) {
37     uint8_t value;
38     if (!Read(addr, &value, sizeof(value))) {
39       return false;
40     }
41     if (value == '\0') {
42       return true;
43     }
44     string->push_back(value);
45     addr++;
46     bytes_read++;
47   }
48   return false;
49 }
50 
Read(uint64_t addr,void * dst,size_t size)51 bool MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
52   uint64_t last_read_byte;
53   if (__builtin_add_overflow(size, addr, &last_read_byte)) {
54     return false;
55   }
56   if (last_read_byte > raw_.size()) {
57     return false;
58   }
59   memcpy(dst, &raw_[addr], size);
60   return true;
61 }
62 
GetPtr(size_t offset)63 uint8_t* MemoryBuffer::GetPtr(size_t offset) {
64   if (offset < raw_.size()) {
65     return &raw_[offset];
66   }
67   return nullptr;
68 }
69 
~MemoryFileAtOffset()70 MemoryFileAtOffset::~MemoryFileAtOffset() {
71   Clear();
72 }
73 
Clear()74 void MemoryFileAtOffset::Clear() {
75   if (data_) {
76     munmap(&data_[-offset_], size_ + offset_);
77     data_ = nullptr;
78   }
79 }
80 
Init(const std::string & file,uint64_t offset,uint64_t size)81 bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset, uint64_t size) {
82   // Clear out any previous data if it exists.
83   Clear();
84 
85   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
86   if (fd == -1) {
87     return false;
88   }
89   struct stat buf;
90   if (fstat(fd, &buf) == -1) {
91     return false;
92   }
93   if (offset >= static_cast<uint64_t>(buf.st_size)) {
94     return false;
95   }
96 
97   offset_ = offset & (getpagesize() - 1);
98   uint64_t aligned_offset = offset & ~(getpagesize() - 1);
99   size_ = buf.st_size - aligned_offset;
100   if (size < (UINT64_MAX - offset_) && size + offset_ < size_) {
101     // Truncate the mapped size.
102     size_ = size + offset_;
103   }
104   void* map = mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd, aligned_offset);
105   if (map == MAP_FAILED) {
106     return false;
107   }
108 
109   data_ = &reinterpret_cast<uint8_t*>(map)[offset_];
110   size_ -= offset_;
111 
112   return true;
113 }
114 
Read(uint64_t addr,void * dst,size_t size)115 bool MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) {
116   if (addr + size > size_) {
117     return false;
118   }
119   memcpy(dst, &data_[addr], size);
120   return true;
121 }
122 
PtraceRead(pid_t pid,uint64_t addr,long * value)123 static bool PtraceRead(pid_t pid, uint64_t addr, long* value) {
124 #if !defined(__LP64__)
125   // Cannot read an address greater than 32 bits.
126   if (addr > UINT32_MAX) {
127     return false;
128   }
129 #endif
130   // ptrace() returns -1 and sets errno when the operation fails.
131   // To disambiguate -1 from a valid result, we clear errno beforehand.
132   errno = 0;
133   *value = ptrace(PTRACE_PEEKTEXT, pid, reinterpret_cast<void*>(addr), nullptr);
134   if (*value == -1 && errno) {
135     return false;
136   }
137   return true;
138 }
139 
Read(uint64_t addr,void * dst,size_t bytes)140 bool MemoryRemote::Read(uint64_t addr, void* dst, size_t bytes) {
141   size_t bytes_read = 0;
142   long data;
143   size_t align_bytes = addr & (sizeof(long) - 1);
144   if (align_bytes != 0) {
145     if (!PtraceRead(pid_, addr & ~(sizeof(long) - 1), &data)) {
146       return false;
147     }
148     size_t copy_bytes = std::min(sizeof(long) - align_bytes, bytes);
149     memcpy(dst, reinterpret_cast<uint8_t*>(&data) + align_bytes, copy_bytes);
150     addr += copy_bytes;
151     dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + copy_bytes);
152     bytes -= copy_bytes;
153     bytes_read += copy_bytes;
154   }
155 
156   for (size_t i = 0; i < bytes / sizeof(long); i++) {
157     if (!PtraceRead(pid_, addr, &data)) {
158       return false;
159     }
160     memcpy(dst, &data, sizeof(long));
161     dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + sizeof(long));
162     addr += sizeof(long);
163     bytes_read += sizeof(long);
164   }
165 
166   size_t left_over = bytes & (sizeof(long) - 1);
167   if (left_over) {
168     if (!PtraceRead(pid_, addr, &data)) {
169       return false;
170     }
171     memcpy(dst, &data, left_over);
172     bytes_read += left_over;
173   }
174   return true;
175 }
176 
Read(uint64_t addr,void * dst,size_t size)177 bool MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
178   // The process_vm_readv call does will not always work on remote
179   // processes, so only use it for reads from the current pid.
180   // Use this method to avoid crashes if an address is invalid since
181   // unwind data could try to access any part of the address space.
182   struct iovec local_io;
183   local_io.iov_base = dst;
184   local_io.iov_len = size;
185 
186   struct iovec remote_io;
187   remote_io.iov_base = reinterpret_cast<void*>(static_cast<uintptr_t>(addr));
188   remote_io.iov_len = size;
189 
190   ssize_t bytes_read = process_vm_readv(getpid(), &local_io, 1, &remote_io, 1, 0);
191   if (bytes_read == -1) {
192     return false;
193   }
194   return static_cast<size_t>(bytes_read) == size;
195 }
196 
Init(const std::string & file,uint64_t offset)197 bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
198   if (!MemoryFileAtOffset::Init(file, offset)) {
199     return false;
200   }
201   // The first uint64_t value is the start of memory.
202   if (!MemoryFileAtOffset::Read(0, &start_, sizeof(start_))) {
203     return false;
204   }
205   // Subtract the first 64 bit value from the total size.
206   size_ -= sizeof(start_);
207   return true;
208 }
209 
Read(uint64_t addr,void * dst,size_t size)210 bool MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
211   if (addr < start_ || addr + size > start_ + offset_ + size_) {
212     return false;
213   }
214   memcpy(dst, &data_[addr + offset_ - start_ + sizeof(start_)], size);
215   return true;
216 }
217