blob: 848e2f3cd8848082ebeb5bc850cc948a55ae0d7e [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,
61 // Poisons based on a custom tracking system which can be specified in
62 // SetDexSections
63 kCustomTracking,
64};
65
66// Intended for local changes only.
67// Represents the current configuration being run.
68static constexpr DexTrackingType kCurrentTrackingSystem = kWholeDexTracking;
69
70// Intended for local changes only.
71void DexFileTrackingRegistrar::SetDexSections() {
Bharadwaj Kalandhabhatta9e1c45d2017-06-13 08:56:51 -070072 if (kDexFileAccessTracking && dex_file_ != nullptr) {
73 // Logs the Dex File's location and starting address if tracking is enabled
74 LOG(ERROR) << "RegisterDexFile: " << dex_file_->GetLocation() + " @ " << std::hex
75 << reinterpret_cast<uintptr_t>(dex_file_->Begin());
Bharadwaj Kalandhabhatta043c9082017-06-06 17:14:12 -070076 switch (kCurrentTrackingSystem) {
77 case kWholeDexTracking:
78 SetDexFileRegistration(true);
79 break;
80 case kCodeItemTracking:
81 SetAllCodeItemRegistration(true);
82 break;
83 case kCodeItemNonInsnsTracking:
84 SetAllCodeItemRegistration(true);
85 SetAllInsnsRegistration(false);
86 break;
87 case kCodeItemNonInsnsNoClinitTracking:
88 SetAllCodeItemRegistration(true);
89 SetAllInsnsRegistration(false);
90 SetCodeItemRegistration("<clinit>", false);
91 break;
92 case kCustomTracking:
93 // TODO: Add/remove additional calls here to (un)poison sections of
94 // dex_file_
95 break;
96 }
97 }
98}
99
100void RegisterDexFile(const DexFile* dex_file) {
101 DexFileTrackingRegistrar dex_tracking_registrar(dex_file);
102 dex_tracking_registrar.SetDexSections();
103 dex_tracking_registrar.SetCurrentRanges();
104}
105
106inline void SetRegistrationRange(const void* begin, size_t size, bool should_poison) {
107 if (should_poison) {
108 MEMORY_TOOL_MAKE_NOACCESS(begin, size);
109 } else {
110 // Note: MEMORY_TOOL_MAKE_UNDEFINED has the same functionality with Address
111 // Sanitizer. The difference has not been tested with Valgrind
112 MEMORY_TOOL_MAKE_DEFINED(begin, size);
113 }
114}
115
116void DexFileTrackingRegistrar::SetCurrentRanges() {
117 // This also empties range_values_ to avoid redundant (un)poisoning upon
118 // subsequent calls.
119 while (!range_values_.empty()) {
120 const std::tuple<const void*, size_t, bool>& current_range = range_values_.front();
121 SetRegistrationRange(std::get<0>(current_range),
122 std::get<1>(current_range),
123 std::get<2>(current_range));
124 range_values_.pop_front();
125 }
126}
127
128void DexFileTrackingRegistrar::SetDexFileRegistration(bool should_poison) {
129 const void* dex_file_begin = reinterpret_cast<const void*>(dex_file_->Begin());
130 size_t dex_file_size = dex_file_->Size();
131 range_values_.push_back(std::make_tuple(dex_file_begin, dex_file_size, should_poison));
132}
133
134void DexFileTrackingRegistrar::SetAllCodeItemRegistration(bool should_poison) {
135 for (size_t classdef_ctr = 0; classdef_ctr < dex_file_->NumClassDefs(); ++classdef_ctr) {
136 const DexFile::ClassDef& cd = dex_file_->GetClassDef(classdef_ctr);
137 const uint8_t* class_data = dex_file_->GetClassData(cd);
138 if (class_data != nullptr) {
139 ClassDataItemIterator cdit(*dex_file_, class_data);
140 // Skipping Fields
141 while (cdit.HasNextStaticField() || cdit.HasNextInstanceField()) {
142 cdit.Next();
143 }
144 while (cdit.HasNextDirectMethod()) {
145 const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
146 if (code_item != nullptr) {
147 const void* code_item_begin = reinterpret_cast<const void*>(code_item);
148 size_t code_item_size = DexFile::GetCodeItemSize(*code_item);
149 range_values_.push_back(std::make_tuple(code_item_begin, code_item_size, should_poison));
150 }
151 cdit.Next();
152 }
153 }
154 }
155}
156
157void DexFileTrackingRegistrar::SetAllInsnsRegistration(bool should_poison) {
158 for (size_t classdef_ctr = 0; classdef_ctr < dex_file_->NumClassDefs(); ++classdef_ctr) {
159 const DexFile::ClassDef& cd = dex_file_->GetClassDef(classdef_ctr);
160 const uint8_t* class_data = dex_file_->GetClassData(cd);
161 if (class_data != nullptr) {
162 ClassDataItemIterator cdit(*dex_file_, class_data);
163 // Skipping Fields
164 while (cdit.HasNextStaticField() || cdit.HasNextInstanceField()) {
165 cdit.Next();
166 }
167 while (cdit.HasNextDirectMethod()) {
168 const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
169 if (code_item != nullptr) {
170 const void* insns_begin = reinterpret_cast<const void*>(&code_item->insns_);
171 // Member insns_size_in_code_units_ is in 2-byte units
172 size_t insns_size = code_item->insns_size_in_code_units_ * 2;
173 range_values_.push_back(std::make_tuple(insns_begin, insns_size, should_poison));
174 }
175 cdit.Next();
176 }
177 }
178 }
179}
180
181void DexFileTrackingRegistrar::SetCodeItemRegistration(const char* class_name, bool should_poison) {
182 for (size_t classdef_ctr = 0; classdef_ctr < dex_file_->NumClassDefs(); ++classdef_ctr) {
183 const DexFile::ClassDef& cd = dex_file_->GetClassDef(classdef_ctr);
184 const uint8_t* class_data = dex_file_->GetClassData(cd);
185 if (class_data != nullptr) {
186 ClassDataItemIterator cdit(*dex_file_, class_data);
187 // Skipping Fields
188 while (cdit.HasNextStaticField() || cdit.HasNextInstanceField()) {
189 cdit.Next();
190 }
191 while (cdit.HasNextDirectMethod()) {
192 const DexFile::MethodId& methodid_item = dex_file_->GetMethodId(cdit.GetMemberIndex());
193 const char * methodid_name = dex_file_->GetMethodName(methodid_item);
194 const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
195 if (code_item != nullptr && strcmp(methodid_name, class_name) == 0) {
196 const void* code_item_begin = reinterpret_cast<const void*>(code_item);
197 size_t code_item_size = DexFile::GetCodeItemSize(*code_item);
198 range_values_.push_back(
199 std::make_tuple(code_item_begin, code_item_size, should_poison));
200 }
201 cdit.Next();
202 }
203 }
Bharadwaj Kalandhabhatta0bb40312017-06-01 10:47:00 -0700204 }
205}
206
207} // namespace tracking
208} // namespace dex
209} // namespace art