Commit 125e4da4 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

v8binding: Replace WrapperCreationSecurityCheck with BindingSecurityForPlatform

This patch introduces a new counter part of BindingSecurity (in core/
component) as BindingSecurityForPlatform (in platform/ component).

BindingSecurityForPlatform is a simple collection of trampolines to
BindingSecurity.

Change-Id: I41195111ff2f288ee3e314048ac92848adf6be0b
Reviewed-on: https://chromium-review.googlesource.com/c/1340439Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609198}
parent e78aab74
......@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_BINDING_SECURITY_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "v8/include/v8.h"
......@@ -45,16 +46,18 @@ class Location;
class Node;
struct WrapperTypeInfo;
// BindingSecurity provides utility functions that determine access permission
// between two realms. For example, is the current Window allowed to access the
// target window?
class CORE_EXPORT BindingSecurity {
STATIC_ONLY(BindingSecurity);
public:
enum class ErrorReportOption {
kDoNotReport,
kReport,
};
using ErrorReportOption = BindingSecurityForPlatform::ErrorReportOption;
// Check if the caller (|accessingWindow|) is allowed to access the JS
static void Init();
// Checks if the caller (|accessing_window|) is allowed to access the JS
// receiver object (|target|), where the receiver object is the JS object
// for which the DOM attribute or DOM operation is being invoked (in the
// form of receiver.domAttr or receiver.domOp()).
......@@ -77,7 +80,7 @@ class CORE_EXPORT BindingSecurity {
const Location* target,
ErrorReportOption);
// Check if the caller (|accessingWindow|) is allowed to access the JS
// Checks if the caller (|accessing_window|) is allowed to access the JS
// returned object (|target|), where the returned object is the JS object
// which is returned as a result of invoking a DOM attribute or DOM
// operation (in the form of
......@@ -105,26 +108,36 @@ class CORE_EXPORT BindingSecurity {
const Frame* target,
ErrorReportOption);
static void FailedAccessCheckFor(v8::Isolate*,
const WrapperTypeInfo*,
v8::Local<v8::Object> holder);
// The following two functions were written to be called by
// V8WrapperInstantiationScope before entering and after exiting an object's
// creation context during wrapper creation.
// Returns true if the current context has access to creationContext, and
// throws a SecurityError if it doesn't have access.
static bool ShouldAllowAccessToCreationContext(
// These overloads should be used only when checking a general access from
// one context to another context. For access to a receiver object or
// returned object, you should use the above overloads.
static bool ShouldAllowAccessToV8Context(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ExceptionState&);
static bool ShouldAllowAccessToV8Context(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ErrorReportOption);
// Checks if a wrapper creation of the given wrapper type associated with
// |creation_context| is allowed in |accessing_context|.
static bool ShouldAllowWrapperCreationOrThrowException(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo*);
const WrapperTypeInfo* wrapper_type_info);
static void RethrowCrossContextException(
// Rethrows a cross context exception, that is possibly cross origin.
// A SecurityError may be rethrown instead of the exception if necessary.
static void RethrowWrapperCreationException(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo*,
const WrapperTypeInfo* wrapper_type_info,
v8::Local<v8::Value> cross_context_exception);
static void InitWrapperCreationSecurityCheck();
static void FailedAccessCheckFor(v8::Isolate*,
const WrapperTypeInfo*,
v8::Local<v8::Object> holder);
private:
// Returns true if |accessingWindow| is allowed named access to |targetWindow|
......
......@@ -103,19 +103,14 @@ void JSBasedEventListener::Invoke(
if (v8_context_of_event_target.IsEmpty())
return;
if (v8_context_of_event_target != script_state_of_listener->GetContext()) {
// Catch exceptions thrown in the event listener if any and report them to
// DevTools console.
v8::TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
// Check if the current context, which is set to the listener's relevant
// context by creating |listener_script_state_scope|, has access to the
// event target's relevant context before creating |js_event|. SecurityError
// is thrown if it doesn't have access.
if (!BindingSecurity::ShouldAllowAccessToCreationContext(
v8_context_of_event_target, event->GetWrapperTypeInfo()))
return;
// Check if the current context, which is set to the listener's relevant
// context by creating |listener_script_state_scope|, has access to the
// event target's relevant context before creating |js_event|. SecurityError
// is thrown if it doesn't have access.
if (!BindingSecurity::ShouldAllowAccessToV8Context(
script_state_of_listener->GetContext(), v8_context_of_event_target,
BindingSecurity::ErrorReportOption::kReport)) {
return;
}
v8::Local<v8::Value> js_event =
......
......@@ -768,8 +768,6 @@ void V8Initializer::InitializeMainThread(const intptr_t* reference_table) {
V8PerIsolateData::From(isolate)->SetThreadDebugger(
std::make_unique<MainThreadDebugger>(isolate));
BindingSecurity::InitWrapperCreationSecurityCheck();
}
static void ReportFatalErrorInWorker(const char* location,
......
......@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/css/media_feature_names.h"
......@@ -145,6 +146,7 @@ void CoreInitializer::Initialize() {
V8ThrowDOMException::Init();
BindingSecurity::Init();
ScriptStreamerThread::Init();
}
......
......@@ -408,6 +408,8 @@ jumbo_component("platform") {
"audio/vector_math_scalar.h",
"bindings/active_script_wrappable_base.cc",
"bindings/active_script_wrappable_base.h",
"bindings/binding_security_for_platform.cc",
"bindings/binding_security_for_platform.h",
"bindings/callback_function_base.cc",
"bindings/callback_function_base.h",
"bindings/callback_interface_base.cc",
......@@ -478,8 +480,6 @@ jumbo_component("platform") {
"bindings/v8_throw_exception.h",
"bindings/v8_value_cache.cc",
"bindings/v8_value_cache.h",
"bindings/wrapper_creation_security_check.cc",
"bindings/wrapper_creation_security_check.h",
"bindings/wrapper_type_info.cc",
"bindings/wrapper_type_info.h",
"content_decryption_module_result.h",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
namespace blink {
BindingSecurityForPlatform::
ShouldAllowAccessToV8ContextWithExceptionStateFunction
BindingSecurityForPlatform::
should_allow_access_to_v8context_with_exception_state_ = nullptr;
BindingSecurityForPlatform::
ShouldAllowAccessToV8ContextWithErrorReportOptionFunction
BindingSecurityForPlatform::
should_allow_access_to_v8context_with_error_report_option_ =
nullptr;
BindingSecurityForPlatform::ShouldAllowWrapperCreationOrThrowExceptionFunction
BindingSecurityForPlatform::
should_allow_wrapper_creation_or_throw_exception_ = nullptr;
BindingSecurityForPlatform::RethrowWrapperCreationExceptionFunction
BindingSecurityForPlatform::rethrow_wrapper_creation_exception_ = nullptr;
// static
bool BindingSecurityForPlatform::ShouldAllowAccessToV8Context(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ExceptionState& exception_state) {
return (*should_allow_access_to_v8context_with_exception_state_)(
accessing_context, target_context, exception_state);
}
// static
bool BindingSecurityForPlatform::ShouldAllowAccessToV8Context(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ErrorReportOption reporting_option) {
return (*should_allow_access_to_v8context_with_error_report_option_)(
accessing_context, target_context, reporting_option);
}
// static
bool BindingSecurityForPlatform::ShouldAllowWrapperCreationOrThrowException(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* wrapper_type_info) {
return (*should_allow_wrapper_creation_or_throw_exception_)(
accessing_context, creation_context, wrapper_type_info);
}
// static
void BindingSecurityForPlatform::RethrowWrapperCreationException(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* wrapper_type_info,
v8::Local<v8::Value> cross_context_exception) {
(*rethrow_wrapper_creation_exception_)(accessing_context, creation_context,
wrapper_type_info,
cross_context_exception);
}
// static
void BindingSecurityForPlatform::
SetShouldAllowAccessToV8ContextWithExceptionState(
ShouldAllowAccessToV8ContextWithExceptionStateFunction func) {
DCHECK(!should_allow_access_to_v8context_with_exception_state_);
DCHECK(func);
should_allow_access_to_v8context_with_exception_state_ = func;
}
// static
void BindingSecurityForPlatform::
SetShouldAllowAccessToV8ContextWithErrorReportOption(
ShouldAllowAccessToV8ContextWithErrorReportOptionFunction func) {
DCHECK(!should_allow_access_to_v8context_with_error_report_option_);
DCHECK(func);
should_allow_access_to_v8context_with_error_report_option_ = func;
}
// static
void BindingSecurityForPlatform::SetShouldAllowWrapperCreationOrThrowException(
ShouldAllowWrapperCreationOrThrowExceptionFunction func) {
DCHECK(!should_allow_wrapper_creation_or_throw_exception_);
DCHECK(func);
should_allow_wrapper_creation_or_throw_exception_ = func;
}
// static
void BindingSecurityForPlatform::SetRethrowWrapperCreationException(
RethrowWrapperCreationExceptionFunction func) {
DCHECK(!rethrow_wrapper_creation_exception_);
DCHECK(func);
rethrow_wrapper_creation_exception_ = func;
}
} // namespace blink
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_BINDING_SECURITY_FOR_PLATFORM_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_BINDING_SECURITY_FOR_PLATFORM_H_
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "v8/include/v8.h"
namespace blink {
class ExceptionState;
struct WrapperTypeInfo;
// BindingSecurityForPlatform provides utility functions that determine access
// permission between two realms.
//
// This class is a collection of trampolines to the actual implementations in
// BindingSecurity in core/ component.
class PLATFORM_EXPORT BindingSecurityForPlatform {
STATIC_ONLY(BindingSecurityForPlatform);
public:
enum class ErrorReportOption {
kDoNotReport,
kReport,
};
// These overloads should be used only when checking a general access from
// one context to another context. For access to a receiver object or
// returned object, you should use BindingSecurity::ShouldAllowAccessTo
// family.
static bool ShouldAllowAccessToV8Context(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ExceptionState&);
static bool ShouldAllowAccessToV8Context(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ErrorReportOption);
// Checks if a wrapper creation of the given wrapper type associated with
// |creation_context| is allowed in |accessing_context|.
static bool ShouldAllowWrapperCreationOrThrowException(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* wrapper_type_info);
// Rethrows a cross context exception, that is possibly cross origin.
// A SecurityError may be rethrown instead of the exception if necessary.
static void RethrowWrapperCreationException(
v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* wrapper_type_info,
v8::Local<v8::Value> cross_context_exception);
private:
using ShouldAllowAccessToV8ContextWithExceptionStateFunction =
bool (*)(v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ExceptionState&);
using ShouldAllowAccessToV8ContextWithErrorReportOptionFunction =
bool (*)(v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> target_context,
ErrorReportOption);
using ShouldAllowWrapperCreationOrThrowExceptionFunction =
bool (*)(v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* wrapper_type_info);
using RethrowWrapperCreationExceptionFunction =
void (*)(v8::Local<v8::Context> accessing_context,
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* wrapper_type_info,
v8::Local<v8::Value> cross_context_exception);
static void SetShouldAllowAccessToV8ContextWithExceptionState(
ShouldAllowAccessToV8ContextWithExceptionStateFunction);
static void SetShouldAllowAccessToV8ContextWithErrorReportOption(
ShouldAllowAccessToV8ContextWithErrorReportOptionFunction);
static void SetShouldAllowWrapperCreationOrThrowException(
ShouldAllowWrapperCreationOrThrowExceptionFunction);
static void SetRethrowWrapperCreationException(
RethrowWrapperCreationExceptionFunction);
static ShouldAllowAccessToV8ContextWithExceptionStateFunction
should_allow_access_to_v8context_with_exception_state_;
static ShouldAllowAccessToV8ContextWithErrorReportOptionFunction
should_allow_access_to_v8context_with_error_report_option_;
static ShouldAllowWrapperCreationOrThrowExceptionFunction
should_allow_wrapper_creation_or_throw_exception_;
static RethrowWrapperCreationExceptionFunction
rethrow_wrapper_creation_exception_;
friend class BindingSecurity;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_BINDING_SECURITY_FOR_PLATFORM_H_
......@@ -32,13 +32,13 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_DOM_WRAPPER_H_
#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
#include "third_party/blink/renderer/platform/bindings/custom_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_creation_security_check.h"
#include "third_party/blink/renderer/platform/heap/unified_heap_marking_visitor.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
......@@ -185,9 +185,8 @@ class V8WrapperInstantiationScope {
if (context_for_wrapper == context_)
return;
context_ = context_for_wrapper;
if (!WrapperCreationSecurityCheck::VerifyContextAccess(context_, type_)) {
if (!BindingSecurityForPlatform::ShouldAllowWrapperCreationOrThrowException(
isolate->GetCurrentContext(), context_for_wrapper, type_)) {
DCHECK(try_catch_.HasCaught());
try_catch_.ReThrow();
access_check_failed_ = true;
......@@ -195,6 +194,7 @@ class V8WrapperInstantiationScope {
}
did_enter_context_ = true;
context_ = context_for_wrapper;
context_->Enter();
}
......@@ -214,8 +214,9 @@ class V8WrapperInstantiationScope {
// such a scenario.
v8::Local<v8::Value> caught_exception = try_catch_.Exception();
try_catch_.Reset();
WrapperCreationSecurityCheck::RethrowCrossContextException(
context_, type_, caught_exception);
BindingSecurityForPlatform::RethrowWrapperCreationException(
context_->GetIsolate()->GetCurrentContext(), context_, type_,
caught_exception);
try_catch_.ReThrow();
}
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/bindings/wrapper_creation_security_check.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
namespace blink {
WrapperCreationSecurityCheck::SecurityCheckFunction
WrapperCreationSecurityCheck::security_check_ = nullptr;
WrapperCreationSecurityCheck::RethrowExceptionFunction
WrapperCreationSecurityCheck::rethrow_exception_ = nullptr;
void WrapperCreationSecurityCheck::SetSecurityCheckFunction(
SecurityCheckFunction func) {
DCHECK(!security_check_);
security_check_ = func;
}
void WrapperCreationSecurityCheck::SetRethrowExceptionFunction(
RethrowExceptionFunction func) {
DCHECK(!rethrow_exception_);
rethrow_exception_ = func;
}
bool WrapperCreationSecurityCheck::VerifyContextAccess(
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* type) {
return (*security_check_)(creation_context, type);
}
void WrapperCreationSecurityCheck::RethrowCrossContextException(
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo* type,
v8::Local<v8::Value> cross_context_exception) {
(*rethrow_exception_)(creation_context, type, cross_context_exception);
}
} // namespace blink
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_WRAPPER_CREATION_SECURITY_CHECK_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_WRAPPER_CREATION_SECURITY_CHECK_H_
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "v8/include/v8.h"
namespace blink {
struct WrapperTypeInfo;
// This class holds pointers to functions that implement creation context access
// and exception rethrowing logic required by V8WrapperInstantiationScope when
// creating wrappers.
class PLATFORM_EXPORT WrapperCreationSecurityCheck {
STATIC_ONLY(WrapperCreationSecurityCheck);
public:
using SecurityCheckFunction = bool (*)(v8::Local<v8::Context>,
const WrapperTypeInfo*);
using RethrowExceptionFunction = void (*)(v8::Local<v8::Context>,
const WrapperTypeInfo*,
v8::Local<v8::Value>);
static void SetSecurityCheckFunction(SecurityCheckFunction);
static void SetRethrowExceptionFunction(RethrowExceptionFunction);
static bool VerifyContextAccess(v8::Local<v8::Context> creation_context,
const WrapperTypeInfo*);
static void RethrowCrossContextException(
v8::Local<v8::Context> creation_context,
const WrapperTypeInfo*,
v8::Local<v8::Value> cross_context_exception);
private:
static SecurityCheckFunction security_check_;
static RethrowExceptionFunction rethrow_exception_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_WRAPPER_CREATION_SECURITY_CHECK_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment