blob: f476028d5f146da4b085897b1e952b90288c575a [file] [log] [blame]
David Brazdil5a61bb72018-01-19 16:59:46 +00001/*
2 * Copyright (C) 2018 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#ifndef ART_RUNTIME_HIDDEN_API_H_
18#define ART_RUNTIME_HIDDEN_API_H_
19
20#include "hidden_api_access_flags.h"
21#include "reflection.h"
22#include "runtime.h"
23
24namespace art {
25namespace hiddenapi {
26
David Brazdila02cb112018-01-31 11:36:39 +000027enum Action {
28 kAllow,
29 kAllowButWarn,
30 kDeny
31};
David Brazdil5a61bb72018-01-19 16:59:46 +000032
David Brazdila02cb112018-01-31 11:36:39 +000033inline Action GetMemberAction(uint32_t access_flags) {
David Brazdil5a61bb72018-01-19 16:59:46 +000034 switch (HiddenApiAccessFlags::DecodeFromRuntime(access_flags)) {
35 case HiddenApiAccessFlags::kWhitelist:
David Brazdila02cb112018-01-31 11:36:39 +000036 return kAllow;
David Brazdil5a61bb72018-01-19 16:59:46 +000037 case HiddenApiAccessFlags::kLightGreylist:
38 case HiddenApiAccessFlags::kDarkGreylist:
David Brazdila02cb112018-01-31 11:36:39 +000039 return kAllowButWarn;
David Brazdil5a61bb72018-01-19 16:59:46 +000040 case HiddenApiAccessFlags::kBlacklist:
David Brazdila02cb112018-01-31 11:36:39 +000041 return kDeny;
David Brazdil5a61bb72018-01-19 16:59:46 +000042 }
43}
44
David Brazdilee7d2fd2018-01-20 17:25:23 +000045// Issue a warning about field access.
46inline void WarnAboutMemberAccess(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdil1077bbc2018-01-31 14:33:08 +000047 std::string tmp;
48 LOG(WARNING) << "Accessing hidden field "
49 << field->GetDeclaringClass()->GetDescriptor(&tmp) << "->"
50 << field->GetName() << ":" << field->GetTypeDescriptor();
David Brazdilee7d2fd2018-01-20 17:25:23 +000051}
52
53// Issue a warning about method access.
54inline void WarnAboutMemberAccess(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdil1077bbc2018-01-31 14:33:08 +000055 std::string tmp;
56 LOG(WARNING) << "Accessing hidden method "
57 << method->GetDeclaringClass()->GetDescriptor(&tmp) << "->"
58 << method->GetName() << method->GetSignature().ToString();
David Brazdilee7d2fd2018-01-20 17:25:23 +000059}
60
David Brazdila02cb112018-01-31 11:36:39 +000061// Returns true if access to `member` should be denied to the caller of the
62// reflective query. The decision is based on whether the caller is in boot
63// class path or not. Because different users of this function determine this
64// in a different way, `fn_caller_in_boot(self)` is called and should return
65// true if the caller is in boot class path.
66// This function might print warnings into the log if the member is greylisted.
David Brazdilee7d2fd2018-01-20 17:25:23 +000067template<typename T>
David Brazdila02cb112018-01-31 11:36:39 +000068inline bool ShouldBlockAccessToMember(T* member,
69 Thread* self,
70 std::function<bool(Thread*)> fn_caller_in_boot)
David Brazdilee7d2fd2018-01-20 17:25:23 +000071 REQUIRES_SHARED(Locks::mutator_lock_) {
72 DCHECK(member != nullptr);
David Brazdila02cb112018-01-31 11:36:39 +000073
74 if (!Runtime::Current()->AreHiddenApiChecksEnabled()) {
75 // Exit early. Nothing to enforce.
76 return false;
David Brazdilee7d2fd2018-01-20 17:25:23 +000077 }
78
David Brazdila02cb112018-01-31 11:36:39 +000079 Action action = GetMemberAction(member->GetAccessFlags());
80 if (action == kAllow) {
81 // Nothing to do.
82 return false;
83 }
84
85 // Member is hidden. Walk the stack to find the caller.
86 // This can be *very* expensive. Save it for last.
87 if (fn_caller_in_boot(self)) {
88 // Caller in boot class path. Exit.
89 return false;
90 }
91
92 // Member is hidden and we are not in the boot class path. Act accordingly.
93 if (action == kAllowButWarn) {
94 // Allow access to this member but print a warning. Depending on a runtime
95 // flag, we might move the member into whitelist and skip the warning the
96 // next time the member is used.
97 Runtime::Current()->SetPendingHiddenApiWarning(true);
98 if (Runtime::Current()->ShouldDedupeHiddenApiWarnings()) {
99 member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
100 member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
101 }
102 WarnAboutMemberAccess(member);
103 return false;
104 } else {
105 DCHECK_EQ(action, hiddenapi::kDeny);
106 return true;
107 }
David Brazdilee7d2fd2018-01-20 17:25:23 +0000108}
109
David Brazdila02cb112018-01-31 11:36:39 +0000110// Returns true if access to member with `access_flags` should be denied to `caller`.
111// This function should be called on statically linked uses of hidden API.
112inline bool ShouldBlockAccessToMember(uint32_t access_flags, mirror::Class* caller)
David Brazdilee7d2fd2018-01-20 17:25:23 +0000113 REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdila02cb112018-01-31 11:36:39 +0000114 if (!Runtime::Current()->AreHiddenApiChecksEnabled()) {
115 // Exit early. Nothing to enforce.
116 return false;
David Brazdilee7d2fd2018-01-20 17:25:23 +0000117 }
118
David Brazdila02cb112018-01-31 11:36:39 +0000119 // Only continue if we want to deny access. Warnings are *not* printed.
120 if (GetMemberAction(access_flags) != kDeny) {
121 return false;
David Brazdilee7d2fd2018-01-20 17:25:23 +0000122 }
123
David Brazdila02cb112018-01-31 11:36:39 +0000124 // Member is hidden. Check if the caller is in boot class path.
125 if (caller == nullptr) {
126 // The caller is unknown. We assume that this is *not* boot class path.
127 return true;
128 }
129
130 return !caller->IsBootStrapClassLoaded();
David Brazdilee7d2fd2018-01-20 17:25:23 +0000131}
132
David Brazdil5a61bb72018-01-19 16:59:46 +0000133} // namespace hiddenapi
134} // namespace art
135
136#endif // ART_RUNTIME_HIDDEN_API_H_