Refactor Core Plaform API checking
Move Core Platform API check logic to hidden_api_jni.{h,cc}.
Use libunwindstack for walking stack as builtin isn't robust without
frame pointers. This is moderately expensive so we currently walk a
maximum of 3 frames.
Checks are now performed by placing ScopedCorePlatformApiCheck
instances at potential points of entry via JNI. Specifically, where
JNI interfaces implement methods for getting field and method ids. The
check is only performed on the outermost instance of the
ScopedCorePlatformApiCheck since only the outer caller is of interest.
State for the checks is stored in the current Thread instance since
the JNI interface signatures are fixed and we need a way to be able to
determine whether a ScopedCorePlatformApiCheck is the outermost
instance and whether the outmost instance was approved.
Test: build eng build (has checkjni), boot, grep logcat nio/Buffer
Test: build user build (regular jni), boot, grep logcat nio/Buffer
Bug: 130336799
Bug: 136276414
Change-Id: If1261046dd57c007bc77b213daaa5f733151123e
diff --git a/runtime/hidden_api_jni.h b/runtime/hidden_api_jni.h
new file mode 100644
index 0000000..a084378
--- /dev/null
+++ b/runtime/hidden_api_jni.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_HIDDEN_API_JNI_H_
+#define ART_RUNTIME_HIDDEN_API_JNI_H_
+
+#include "base/macros.h"
+
+namespace art {
+
+class Thread;
+
+namespace hiddenapi {
+
+// Stack markers that should be instantiated in JNI Get{Field,Method}Id methods (and
+// their static equivalents) to allow native caller checks to take place.
+class ScopedCorePlatformApiCheck final {
+ public:
+ ScopedCorePlatformApiCheck();
+ ~ScopedCorePlatformApiCheck();
+
+ // Check whether the caller is automatically approved based on location. Code in the run-time or
+ // in an APEX is considered to be automatically approved.
+ static bool IsCurrentCallerApproved(Thread* self);
+
+ private:
+ // Captures calling PC for frame above the frame allocating the current ScopedCorePlatformApiCheck
+ // instance.
+ void* CaptureCallerPc();
+
+ // Instances should only be stack allocated, copy and assignment not useful.
+ DISALLOW_ALLOCATION();
+ DISALLOW_COPY_AND_ASSIGN(ScopedCorePlatformApiCheck);
+};
+
+void JniInitializeNativeCallerCheck();
+void JniShutdownNativeCallerCheck();
+
+} // namespace hiddenapi
+} // namespace art
+
+#endif // ART_RUNTIME_HIDDEN_API_JNI_H_