blob: 341158671b80e5475ae5a7851e92e9040a1f7a57 [file] [log] [blame]
Bharadwaj Kalandhabhatta0bb40312017-06-01 10:47:00 -07001/*
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 "dex_file_tracking_registrar.h"
18
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -070019#include <deque>
20#include <tuple>
21
Bharadwaj Kalandhabhatta0bb40312017-06-01 10:47:00 -070022// For dex tracking through poisoning. Note: Requires forcing sanitization. This is the reason for
23// the ifdefs and early include.
24#ifdef ART_DEX_FILE_ACCESS_TRACKING
25#ifndef ART_ENABLE_ADDRESS_SANITIZER
26#define ART_ENABLE_ADDRESS_SANITIZER
27#endif
28#endif
29#include "base/memory_tool.h"
30
31#include "base/logging.h"
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -070032#include "dex_file-inl.h"
Bharadwaj Kalandhabhatta0bb40312017-06-01 10:47:00 -070033
34namespace art {
35namespace dex {
36namespace tracking {
37
38// If true, poison dex files to track accesses.
39static constexpr bool kDexFileAccessTracking =
40#ifdef ART_DEX_FILE_ACCESS_TRACKING
41 true;
42#else
43 false;
44#endif
45
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -070046// The following are configurations of poisoning certain sections of a Dex File.
47// More will be added
48enum DexTrackingType {
49 // Poisons all of a Dex File when set.
50 kWholeDexTracking,
51 // Poisons all Code Items of a Dex File when set.
52 kCodeItemTracking,
53 // Poisons all subsections of a Code Item, except the Insns bytecode array
54 // section, when set for all Code Items in a Dex File.
55 kCodeItemNonInsnsTracking,
56 // Poisons all subsections of a Code Item, except the Insns bytecode array
57 // section, when set for all Code Items in a Dex File.
58 // Additionally unpoisons the entire Code Item when method is a class
59 // initializer.
60 kCodeItemNonInsnsNoClinitTracking,
Bharadwaj Kalandhabhattaab7e45a2017-07-06 10:05:31 -070061 // Poisons the size and offset information along with the first instruction.
62 // This is so that accessing multiple instructions while accessing a code item
63 // once will not trigger unnecessary accesses.
64 kCodeItemStartTracking,
65 // Poisons all String Data Items of a Dex Files when set.
66 kStringDataItemTracking,
67 // Poisons the first byte of the utf16_size value and the first byte of the
68 // data section for all String Data Items of a Dex File.
69 kStringDataItemStartTracking,
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -070070 // Poisons based on a custom tracking system which can be specified in
71 // SetDexSections
72 kCustomTracking,
73};
74
75// Intended for local changes only.
76// Represents the current configuration being run.
77static constexpr DexTrackingType kCurrentTrackingSystem = kWholeDexTracking;
78
79// Intended for local changes only.
80void DexFileTrackingRegistrar::SetDexSections() {
Bharadwaj Kalandhabhatta9e1c45d2017-06-13 08:56:51 -070081 if (kDexFileAccessTracking && dex_file_ != nullptr) {
82 // Logs the Dex File's location and starting address if tracking is enabled
83 LOG(ERROR) << "RegisterDexFile: " << dex_file_->GetLocation() + " @ " << std::hex
84 << reinterpret_cast<uintptr_t>(dex_file_->Begin());
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -070085 switch (kCurrentTrackingSystem) {
86 case kWholeDexTracking:
87 SetDexFileRegistration(true);
88 break;
89 case kCodeItemTracking:
90 SetAllCodeItemRegistration(true);
91 break;
92 case kCodeItemNonInsnsTracking:
93 SetAllCodeItemRegistration(true);
94 SetAllInsnsRegistration(false);
95 break;
96 case kCodeItemNonInsnsNoClinitTracking:
97 SetAllCodeItemRegistration(true);
98 SetAllInsnsRegistration(false);
99 SetCodeItemRegistration("<clinit>", false);
100 break;
Bharadwaj Kalandhabhattaab7e45a2017-07-06 10:05:31 -0700101 case kCodeItemStartTracking:
102 SetAllCodeItemStartRegistration(true);
103 break;
104 case kStringDataItemTracking:
105 SetAllStringDataRegistration(true);
106 break;
107 case kStringDataItemStartTracking:
108 SetAllStringDataStartRegistration(true);
109 break;
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -0700110 case kCustomTracking:
111 // TODO: Add/remove additional calls here to (un)poison sections of
112 // dex_file_
113 break;
Bharadwaj Kalandhabhattaab7e45a2017-07-06 10:05:31 -0700114 default:
115 break;
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -0700116 }
117 }
118}
119
120void RegisterDexFile(const DexFile* dex_file) {
121 DexFileTrackingRegistrar dex_tracking_registrar(dex_file);
122 dex_tracking_registrar.SetDexSections();
123 dex_tracking_registrar.SetCurrentRanges();
124}
125
126inline void SetRegistrationRange(const void* begin, size_t size, bool should_poison) {
127 if (should_poison) {
128 MEMORY_TOOL_MAKE_NOACCESS(begin, size);
129 } else {
130 // Note: MEMORY_TOOL_MAKE_UNDEFINED has the same functionality with Address
131 // Sanitizer. The difference has not been tested with Valgrind
132 MEMORY_TOOL_MAKE_DEFINED(begin, size);
133 }
134}
135
136void DexFileTrackingRegistrar::SetCurrentRanges() {
137 // This also empties range_values_ to avoid redundant (un)poisoning upon
138 // subsequent calls.
139 while (!range_values_.empty()) {
140 const std::tuple<const void*, size_t, bool>& current_range = range_values_.front();
141 SetRegistrationRange(std::get<0>(current_range),
142 std::get<1>(current_range),
143 std::get<2>(current_range));
144 range_values_.pop_front();
145 }
146}
147
148void DexFileTrackingRegistrar::SetDexFileRegistration(bool should_poison) {
149 const void* dex_file_begin = reinterpret_cast<const void*>(dex_file_->Begin());
150 size_t dex_file_size = dex_file_->Size();
151 range_values_.push_back(std::make_tuple(dex_file_begin, dex_file_size, should_poison));
152}
153
154void DexFileTrackingRegistrar::SetAllCodeItemRegistration(bool should_poison) {
155 for (size_t classdef_ctr = 0; classdef_ctr < dex_file_->NumClassDefs(); ++classdef_ctr) {
156 const DexFile::ClassDef& cd = dex_file_->GetClassDef(classdef_ctr);
157 const uint8_t* class_data = dex_file_->GetClassData(cd);
158 if (class_data != nullptr) {
159 ClassDataItemIterator cdit(*dex_file_, class_data);
Mathieu Chartiere17cf242017-06-19 11:05:51 -0700160 cdit.SkipAllFields();
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -0700161 while (cdit.HasNextDirectMethod()) {
162 const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
163 if (code_item != nullptr) {
164 const void* code_item_begin = reinterpret_cast<const void*>(code_item);
165 size_t code_item_size = DexFile::GetCodeItemSize(*code_item);
166 range_values_.push_back(std::make_tuple(code_item_begin, code_item_size, should_poison));
167 }
168 cdit.Next();
169 }
170 }
171 }
172}
173
Bharadwaj Kalandhabhattaab7e45a2017-07-06 10:05:31 -0700174void DexFileTrackingRegistrar::SetAllCodeItemStartRegistration(bool should_poison) {
175 for (size_t classdef_ctr = 0; classdef_ctr < dex_file_->NumClassDefs(); ++classdef_ctr) {
176 const DexFile::ClassDef& cd = dex_file_->GetClassDef(classdef_ctr);
177 const uint8_t* class_data = dex_file_->GetClassData(cd);
178 if (class_data != nullptr) {
179 ClassDataItemIterator cdit(*dex_file_, class_data);
180 cdit.SkipAllFields();
181 while (cdit.HasNextDirectMethod()) {
182 const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
183 if (code_item != nullptr) {
184 const void* code_item_begin = reinterpret_cast<const void*>(code_item);
185 size_t code_item_start = reinterpret_cast<size_t>(code_item);
186 size_t code_item_start_end = reinterpret_cast<size_t>(&code_item->insns_[1]);
187 size_t code_item_start_size = code_item_start_end - code_item_start;
188 range_values_.push_back(std::make_tuple(code_item_begin, code_item_start_size, should_poison));
189 }
190 cdit.Next();
191 }
192 }
193 }
194}
195
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -0700196void DexFileTrackingRegistrar::SetAllInsnsRegistration(bool should_poison) {
197 for (size_t classdef_ctr = 0; classdef_ctr < dex_file_->NumClassDefs(); ++classdef_ctr) {
198 const DexFile::ClassDef& cd = dex_file_->GetClassDef(classdef_ctr);
199 const uint8_t* class_data = dex_file_->GetClassData(cd);
200 if (class_data != nullptr) {
201 ClassDataItemIterator cdit(*dex_file_, class_data);
Mathieu Chartiere17cf242017-06-19 11:05:51 -0700202 cdit.SkipAllFields();
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -0700203 while (cdit.HasNextDirectMethod()) {
204 const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
205 if (code_item != nullptr) {
206 const void* insns_begin = reinterpret_cast<const void*>(&code_item->insns_);
207 // Member insns_size_in_code_units_ is in 2-byte units
208 size_t insns_size = code_item->insns_size_in_code_units_ * 2;
209 range_values_.push_back(std::make_tuple(insns_begin, insns_size, should_poison));
210 }
211 cdit.Next();
212 }
213 }
214 }
215}
216
217void DexFileTrackingRegistrar::SetCodeItemRegistration(const char* class_name, bool should_poison) {
218 for (size_t classdef_ctr = 0; classdef_ctr < dex_file_->NumClassDefs(); ++classdef_ctr) {
219 const DexFile::ClassDef& cd = dex_file_->GetClassDef(classdef_ctr);
220 const uint8_t* class_data = dex_file_->GetClassData(cd);
221 if (class_data != nullptr) {
222 ClassDataItemIterator cdit(*dex_file_, class_data);
Mathieu Chartiere17cf242017-06-19 11:05:51 -0700223 cdit.SkipAllFields();
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -0700224 while (cdit.HasNextDirectMethod()) {
225 const DexFile::MethodId& methodid_item = dex_file_->GetMethodId(cdit.GetMemberIndex());
226 const char * methodid_name = dex_file_->GetMethodName(methodid_item);
227 const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
228 if (code_item != nullptr && strcmp(methodid_name, class_name) == 0) {
229 const void* code_item_begin = reinterpret_cast<const void*>(code_item);
230 size_t code_item_size = DexFile::GetCodeItemSize(*code_item);
Bharadwaj Kalandhabhattaab7e45a2017-07-06 10:05:31 -0700231 range_values_.push_back(std::make_tuple(code_item_begin, code_item_size, should_poison));
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -0700232 }
233 cdit.Next();
234 }
235 }
Bharadwaj Kalandhabhatta0bb40312017-06-01 10:47:00 -0700236 }
237}
238
Bharadwaj Kalandhabhattaab7e45a2017-07-06 10:05:31 -0700239void DexFileTrackingRegistrar::SetAllStringDataStartRegistration(bool should_poison) {
240 for (size_t stringid_ctr = 0; stringid_ctr < dex_file_->NumStringIds(); ++stringid_ctr) {
241 const DexFile::StringId & string_id = dex_file_->GetStringId(StringIndex(stringid_ctr));
242 const void* string_data_begin = reinterpret_cast<const void*>(dex_file_->Begin() + string_id.string_data_off_);
243 // Data Section of String Data Item
244 const void* string_data_data_begin = reinterpret_cast<const void*>(dex_file_->GetStringData(string_id));
245 range_values_.push_back(std::make_tuple(string_data_begin, 1, should_poison));
246 range_values_.push_back(std::make_tuple(string_data_data_begin, 1, should_poison));
247 }
248}
249
250void DexFileTrackingRegistrar::SetAllStringDataRegistration(bool should_poison) {
251 size_t map_offset = dex_file_->GetHeader().map_off_;
252 auto map_list = reinterpret_cast<const DexFile::MapList*>(dex_file_->Begin() + map_offset);
253 for (size_t map_ctr = 0; map_ctr < map_list->size_; ++map_ctr) {
254 const DexFile::MapItem& map_item = map_list->list_[map_ctr];
255 if (map_item.type_ == DexFile::kDexTypeStringDataItem) {
256 const DexFile::MapItem& next_map_item = map_list->list_[map_ctr + 1];
257 const void* string_data_begin = reinterpret_cast<const void*>(dex_file_->Begin() + map_item.offset_);
258 size_t string_data_size = next_map_item.offset_ - map_item.offset_;
259 range_values_.push_back(std::make_tuple(string_data_begin, string_data_size, should_poison));
260 }
261 }
262}
263
Bharadwaj Kalandhabhatta0bb40312017-06-01 10:47:00 -0700264} // namespace tracking
265} // namespace dex
266} // namespace art