Block access to java.lang.Object.getClass in injected Java objects
Prevents invocations of java.lang.Object.getClass from JavaScript code via an
injected Java object.
On an invocation attempt, logs an EventLog message, and sends a message to
WebChromeClient.onConsoleMessage callback.
Bug: 13694467
Change-Id: I9eab38aac48c6ae4ad49dd06c67c8ccf0af17ea7
diff --git a/content/browser/renderer_host/java/java_bound_object.cc b/content/browser/renderer_host/java/java_bound_object.cc
index e2ad87a..a790816 100644
--- a/content/browser/renderer_host/java/java_bound_object.cc
+++ b/content/browser/renderer_host/java/java_bound_object.cc
@@ -4,6 +4,9 @@
#include "content/browser/renderer_host/java/java_bound_object.h"
+#include <log/log.h>
+#include <unistd.h>
+
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/memory/singleton.h"
@@ -45,6 +48,8 @@
const char kReturningJavaLangReflectMethodArray[] =
"()[Ljava/lang/reflect/Method;";
const char kTakesJavaLangClassReturningBoolean[] = "(Ljava/lang/Class;)Z";
+const char kAccessToObjectGetClassIsBlocked[] =
+ "Access to java.lang.Object.getClass is blocked";
// Our special NPObject type. We extend an NPObject with a pointer to a
// JavaBoundObject. We also add static methods for each of the NPObject
@@ -797,6 +802,7 @@
: java_object_(AttachCurrentThread(), object.obj()),
manager_(manager),
are_methods_set_up_(false),
+ object_get_class_method_id_(NULL),
safe_annotation_clazz_(safe_annotation_clazz) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -853,6 +859,22 @@
return false;
}
+ // Block access to java.lang.Object.getClass.
+ // As it is declared to be final, it is sufficient to compare methodIDs.
+ if (method->id() == object_get_class_method_id_) {
+ // See frameworks/base/core/java/android/webkit/EventLogTags.logtags
+ LOG_EVENT_INT(70151, getuid());
+ // Also, send a message to WebChromeClient.onConsoleMessage callback
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&JavaBridgeDispatcherHostManager::AddMessageToConsole,
+ manager_,
+ logging::LOG_ERROR,
+ kAccessToObjectGetClassIsBlocked));
+ return false;
+ }
+
// Coerce
std::vector<jvalue> parameters(arg_count);
for (size_t i = 0; i < arg_count; ++i) {
@@ -888,6 +910,13 @@
are_methods_set_up_ = true;
JNIEnv* env = AttachCurrentThread();
+
+ object_get_class_method_id_ = GetMethodIDFromClassName(
+ env,
+ kJavaLangObject,
+ kGetClass,
+ kReturningJavaLangClass);
+
ScopedJavaLocalRef<jobject> obj = java_object_.get(env);
if (obj.is_null()) {
@@ -895,11 +924,7 @@
}
ScopedJavaLocalRef<jclass> clazz(env, static_cast<jclass>(
- env->CallObjectMethod(obj.obj(), GetMethodIDFromClassName(
- env,
- kJavaLangObject,
- kGetClass,
- kReturningJavaLangClass))));
+ env->CallObjectMethod(obj.obj(), object_get_class_method_id_)));
ScopedJavaLocalRef<jobjectArray> methods(env, static_cast<jobjectArray>(
env->CallObjectMethod(clazz.obj(), GetMethodIDFromClassName(
diff --git a/content/browser/renderer_host/java/java_bound_object.h b/content/browser/renderer_host/java/java_bound_object.h
index ff97fdb..6b10e4f 100644
--- a/content/browser/renderer_host/java/java_bound_object.h
+++ b/content/browser/renderer_host/java/java_bound_object.h
@@ -78,6 +78,7 @@
typedef std::multimap<std::string, linked_ptr<JavaMethod> > JavaMethodMap;
mutable JavaMethodMap methods_;
mutable bool are_methods_set_up_;
+ mutable jmethodID object_get_class_method_id_;
base::android::ScopedJavaGlobalRef<jclass> safe_annotation_clazz_;
diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
index 02cf4dc..be46f68 100644
--- a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
+++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
@@ -7,6 +7,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_helper.h"
#include "base/android/scoped_java_ref.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
@@ -14,6 +15,8 @@
#include "content/browser/renderer_host/java/java_bridge_dispatcher_host.h"
#include "content/common/android/hash_set.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
#include "third_party/WebKit/public/web/WebBindings.h"
namespace content {
@@ -154,4 +157,13 @@
}
}
+void JavaBridgeDispatcherHostManager::AddMessageToConsole(
+ int32 level,
+ const char* message) {
+ WebContentsDelegate* delegate = web_contents()->GetDelegate();
+ if (delegate)
+ delegate->AddMessageToConsole(
+ web_contents(), level, ASCIIToUTF16(message), 0, ASCIIToUTF16(""));
+}
+
} // namespace content
diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
index 29523b5..602f1bf 100644
--- a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
+++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.h
@@ -56,6 +56,8 @@
void JavaBoundObjectCreated(const base::android::JavaRef<jobject>& object);
void JavaBoundObjectDestroyed(const base::android::JavaRef<jobject>& object);
+ void AddMessageToConsole(int32 level, const char* message);
+
private:
typedef std::map<RenderViewHost*, scoped_refptr<JavaBridgeDispatcherHost> >
InstanceMap;