Commit 133d4a88 authored by jochen's avatar jochen Committed by Commit bot

Plumb accessing context through to access control callbacks

BUG=none
LOG=n
R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/1410883006

Cr-Commit-Position: refs/heads/master@{#31495}
parent 2e5845f1
...@@ -4251,6 +4251,14 @@ enum AccessType { ...@@ -4251,6 +4251,14 @@ enum AccessType {
}; };
/**
* Returns true if the given context should be allowed to access the given
* object.
*/
typedef bool (*AccessCheckCallback)(Local<Context> accessing_context,
Local<Object> accessed_object);
/** /**
* Returns true if cross-context access should be allowed to the named * Returns true if cross-context access should be allowed to the named
* property with the given key on the host object. * property with the given key on the host object.
...@@ -4659,16 +4667,20 @@ class V8_EXPORT ObjectTemplate : public Template { ...@@ -4659,16 +4667,20 @@ class V8_EXPORT ObjectTemplate : public Template {
void MarkAsUndetectable(); void MarkAsUndetectable();
/** /**
* Sets access check callbacks on the object template and enables * Sets access check callback on the object template and enables access
* access checks. * checks.
* *
* When accessing properties on instances of this object template, * When accessing properties on instances of this object template,
* the access check callback will be called to determine whether or * the access check callback will be called to determine whether or
* not to allow cross-context access to the properties. * not to allow cross-context access to the properties.
*/ */
void SetAccessCheckCallbacks(NamedSecurityCallback named_handler, void SetAccessCheckCallback(AccessCheckCallback callback);
IndexedSecurityCallback indexed_handler,
Local<Value> data = Local<Value>()); V8_DEPRECATE_SOON(
"Use SetAccessCheckCallback instead",
void SetAccessCheckCallbacks(NamedSecurityCallback named_handler,
IndexedSecurityCallback indexed_handler,
Local<Value> data = Local<Value>()));
/** /**
* Gets the number of internal fields for objects generated from * Gets the number of internal fields for objects generated from
......
...@@ -1452,6 +1452,29 @@ void ObjectTemplate::MarkAsUndetectable() { ...@@ -1452,6 +1452,29 @@ void ObjectTemplate::MarkAsUndetectable() {
} }
void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ENTER_V8(isolate);
i::HandleScope scope(isolate);
auto cons = EnsureConstructor(isolate, this);
EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallback");
i::Handle<i::Struct> struct_info =
isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
i::Handle<i::AccessCheckInfo> info =
i::Handle<i::AccessCheckInfo>::cast(struct_info);
SET_FIELD_WRAPPED(info, set_callback, callback);
SET_FIELD_WRAPPED(info, set_named_callback, nullptr);
SET_FIELD_WRAPPED(info, set_indexed_callback, nullptr);
info->set_data(*isolate->factory()->undefined_value());
cons->set_access_check_info(*info);
cons->set_needs_access_check(true);
}
void ObjectTemplate::SetAccessCheckCallbacks( void ObjectTemplate::SetAccessCheckCallbacks(
NamedSecurityCallback named_callback, NamedSecurityCallback named_callback,
IndexedSecurityCallback indexed_callback, Local<Value> data) { IndexedSecurityCallback indexed_callback, Local<Value> data) {
...@@ -1466,6 +1489,7 @@ void ObjectTemplate::SetAccessCheckCallbacks( ...@@ -1466,6 +1489,7 @@ void ObjectTemplate::SetAccessCheckCallbacks(
i::Handle<i::AccessCheckInfo> info = i::Handle<i::AccessCheckInfo> info =
i::Handle<i::AccessCheckInfo>::cast(struct_info); i::Handle<i::AccessCheckInfo>::cast(struct_info);
SET_FIELD_WRAPPED(info, set_callback, nullptr);
SET_FIELD_WRAPPED(info, set_named_callback, named_callback); SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback); SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
......
...@@ -812,27 +812,33 @@ bool Isolate::MayAccess(Handle<Context> accessing_context, ...@@ -812,27 +812,33 @@ bool Isolate::MayAccess(Handle<Context> accessing_context,
HandleScope scope(this); HandleScope scope(this);
Handle<Object> data; Handle<Object> data;
v8::NamedSecurityCallback callback; v8::AccessCheckCallback callback = nullptr;
v8::NamedSecurityCallback named_callback = nullptr;
{ DisallowHeapAllocation no_gc; { DisallowHeapAllocation no_gc;
AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver);
if (!access_check_info) return false; if (!access_check_info) return false;
Object* fun_obj = access_check_info->named_callback(); Object* fun_obj = access_check_info->callback();
callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj); callback = v8::ToCData<v8::AccessCheckCallback>(fun_obj);
if (!callback) return false; if (!callback) {
data = handle(access_check_info->data(), this); fun_obj = access_check_info->named_callback();
named_callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
if (!named_callback) return false;
data = handle(access_check_info->data(), this);
}
} }
LOG(this, ApiSecurityCheck()); LOG(this, ApiSecurityCheck());
{ {
SaveContext save(this);
set_context(accessing_context->native_context());
// Leaving JavaScript. // Leaving JavaScript.
VMState<EXTERNAL> state(this); VMState<EXTERNAL> state(this);
if (callback) {
return callback(v8::Utils::ToLocal(accessing_context),
v8::Utils::ToLocal(receiver));
}
Handle<Object> key = factory()->undefined_value(); Handle<Object> key = factory()->undefined_value();
return callback(v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(key), return named_callback(v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(key),
v8::ACCESS_HAS, v8::Utils::ToLocal(data)); v8::ACCESS_HAS, v8::Utils::ToLocal(data));
} }
} }
......
...@@ -929,6 +929,7 @@ void AccessCheckInfo::AccessCheckInfoVerify() { ...@@ -929,6 +929,7 @@ void AccessCheckInfo::AccessCheckInfoVerify() {
CHECK(IsAccessCheckInfo()); CHECK(IsAccessCheckInfo());
VerifyPointer(named_callback()); VerifyPointer(named_callback());
VerifyPointer(indexed_callback()); VerifyPointer(indexed_callback());
VerifyPointer(callback());
VerifyPointer(data()); VerifyPointer(data());
} }
......
...@@ -5659,6 +5659,7 @@ ACCESSORS(AccessorPair, setter, Object, kSetterOffset) ...@@ -5659,6 +5659,7 @@ ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset) ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset) ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
ACCESSORS(AccessCheckInfo, callback, Object, kCallbackOffset)
ACCESSORS(AccessCheckInfo, data, Object, kDataOffset) ACCESSORS(AccessCheckInfo, data, Object, kDataOffset)
ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset) ACCESSORS(InterceptorInfo, getter, Object, kGetterOffset)
......
...@@ -1015,6 +1015,7 @@ void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) { // NOLINT ...@@ -1015,6 +1015,7 @@ void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "AccessCheckInfo"); HeapObject::PrintHeader(os, "AccessCheckInfo");
os << "\n - named_callback: " << Brief(named_callback()); os << "\n - named_callback: " << Brief(named_callback());
os << "\n - indexed_callback: " << Brief(indexed_callback()); os << "\n - indexed_callback: " << Brief(indexed_callback());
os << "\n - callback: " << Brief(callback());
os << "\n - data: " << Brief(data()); os << "\n - data: " << Brief(data());
os << "\n"; os << "\n";
} }
......
...@@ -10317,6 +10317,7 @@ class AccessCheckInfo: public Struct { ...@@ -10317,6 +10317,7 @@ class AccessCheckInfo: public Struct {
public: public:
DECL_ACCESSORS(named_callback, Object) DECL_ACCESSORS(named_callback, Object)
DECL_ACCESSORS(indexed_callback, Object) DECL_ACCESSORS(indexed_callback, Object)
DECL_ACCESSORS(callback, Object)
DECL_ACCESSORS(data, Object) DECL_ACCESSORS(data, Object)
DECLARE_CAST(AccessCheckInfo) DECLARE_CAST(AccessCheckInfo)
...@@ -10327,7 +10328,8 @@ class AccessCheckInfo: public Struct { ...@@ -10327,7 +10328,8 @@ class AccessCheckInfo: public Struct {
static const int kNamedCallbackOffset = HeapObject::kHeaderSize; static const int kNamedCallbackOffset = HeapObject::kHeaderSize;
static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize; static const int kIndexedCallbackOffset = kNamedCallbackOffset + kPointerSize;
static const int kDataOffset = kIndexedCallbackOffset + kPointerSize; static const int kCallbackOffset = kIndexedCallbackOffset + kPointerSize;
static const int kDataOffset = kCallbackOffset + kPointerSize;
static const int kSize = kDataOffset + kPointerSize; static const int kSize = kDataOffset + kPointerSize;
private: private:
......
...@@ -610,8 +610,8 @@ THREADED_TEST(Regress433458) { ...@@ -610,8 +610,8 @@ THREADED_TEST(Regress433458) {
static bool security_check_value = false; static bool security_check_value = false;
static bool SecurityTestCallback(Local<v8::Object> global, Local<Value> name, static bool SecurityTestCallback(Local<v8::Context> accessing_context,
v8::AccessType type, Local<Value> data) { Local<v8::Object> accessed_object) {
return security_check_value; return security_check_value;
} }
...@@ -627,7 +627,7 @@ TEST(PrototypeGetterAccessCheck) { ...@@ -627,7 +627,7 @@ TEST(PrototypeGetterAccessCheck) {
fun_templ->InstanceTemplate()->SetAccessorProperty(v8_str("foo"), fun_templ->InstanceTemplate()->SetAccessorProperty(v8_str("foo"),
getter_templ); getter_templ);
auto obj_templ = v8::ObjectTemplate::New(isolate); auto obj_templ = v8::ObjectTemplate::New(isolate);
obj_templ->SetAccessCheckCallbacks(SecurityTestCallback, nullptr); obj_templ->SetAccessCheckCallback(SecurityTestCallback);
env->Global()->Set(v8_str("Fun"), fun_templ->GetFunction()); env->Global()->Set(v8_str("Fun"), fun_templ->GetFunction());
env->Global()->Set(v8_str("obj"), obj_templ->NewInstance()); env->Global()->Set(v8_str("obj"), obj_templ->NewInstance());
env->Global()->Set(v8_str("obj2"), obj_templ->NewInstance()); env->Global()->Set(v8_str("obj2"), obj_templ->NewInstance());
......
...@@ -1660,8 +1660,8 @@ THREADED_TEST(IndexedInterceptorWithNoSetter) { ...@@ -1660,8 +1660,8 @@ THREADED_TEST(IndexedInterceptorWithNoSetter) {
} }
static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name, static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
v8::AccessType type, Local<Value> data) { Local<v8::Object> accessed_object) {
return false; return false;
} }
...@@ -1673,7 +1673,7 @@ THREADED_TEST(IndexedInterceptorWithAccessorCheck) { ...@@ -1673,7 +1673,7 @@ THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
templ->SetHandler( templ->SetHandler(
v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter)); v8::IndexedPropertyHandlerConfiguration(IdentityIndexedPropertyGetter));
templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, nullptr); templ->SetAccessCheckCallback(AccessAlwaysBlocked);
LocalContext context; LocalContext context;
Local<v8::Object> obj = templ->NewInstance(); Local<v8::Object> obj = templ->NewInstance();
...@@ -2907,12 +2907,13 @@ struct AccessCheckData { ...@@ -2907,12 +2907,13 @@ struct AccessCheckData {
bool result; bool result;
}; };
AccessCheckData* g_access_check_data = nullptr;
bool SimpleAccessChecker(Local<v8::Object> global, Local<Value> name,
v8::AccessType type, Local<Value> data) { bool SimpleAccessChecker(Local<v8::Context> accessing_context,
auto access_check_data = GetWrappedObject<AccessCheckData>(data); Local<v8::Object> access_object) {
access_check_data->count++; g_access_check_data->count++;
return access_check_data->result; return g_access_check_data->result;
} }
...@@ -2944,7 +2945,7 @@ void ShouldIndexedInterceptor(uint32_t, ...@@ -2944,7 +2945,7 @@ void ShouldIndexedInterceptor(uint32_t,
} // namespace } // namespace
THREADED_TEST(NamedAllCanReadInterceptor) { TEST(NamedAllCanReadInterceptor) {
auto isolate = CcTest::isolate(); auto isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
LocalContext context; LocalContext context;
...@@ -2953,6 +2954,8 @@ THREADED_TEST(NamedAllCanReadInterceptor) { ...@@ -2953,6 +2954,8 @@ THREADED_TEST(NamedAllCanReadInterceptor) {
access_check_data.result = true; access_check_data.result = true;
access_check_data.count = 0; access_check_data.count = 0;
g_access_check_data = &access_check_data;
ShouldInterceptData intercept_data_0; ShouldInterceptData intercept_data_0;
intercept_data_0.value = 239; intercept_data_0.value = 239;
intercept_data_0.should_intercept = true; intercept_data_0.should_intercept = true;
...@@ -2980,9 +2983,7 @@ THREADED_TEST(NamedAllCanReadInterceptor) { ...@@ -2980,9 +2983,7 @@ THREADED_TEST(NamedAllCanReadInterceptor) {
} }
auto checked = v8::ObjectTemplate::New(isolate); auto checked = v8::ObjectTemplate::New(isolate);
checked->SetAccessCheckCallbacks( checked->SetAccessCheckCallback(SimpleAccessChecker);
SimpleAccessChecker, nullptr,
BuildWrappedObject<AccessCheckData>(isolate, &access_check_data));
context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance()); context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance());
context->Global()->Set(v8_str("intercepted_1"), intercepted_1->NewInstance()); context->Global()->Set(v8_str("intercepted_1"), intercepted_1->NewInstance());
...@@ -3017,10 +3018,11 @@ THREADED_TEST(NamedAllCanReadInterceptor) { ...@@ -3017,10 +3018,11 @@ THREADED_TEST(NamedAllCanReadInterceptor) {
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
} }
CHECK_EQ(9, access_check_data.count); CHECK_EQ(9, access_check_data.count);
g_access_check_data = nullptr;
} }
THREADED_TEST(IndexedAllCanReadInterceptor) { TEST(IndexedAllCanReadInterceptor) {
auto isolate = CcTest::isolate(); auto isolate = CcTest::isolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
LocalContext context; LocalContext context;
...@@ -3029,6 +3031,8 @@ THREADED_TEST(IndexedAllCanReadInterceptor) { ...@@ -3029,6 +3031,8 @@ THREADED_TEST(IndexedAllCanReadInterceptor) {
access_check_data.result = true; access_check_data.result = true;
access_check_data.count = 0; access_check_data.count = 0;
g_access_check_data = &access_check_data;
ShouldInterceptData intercept_data_0; ShouldInterceptData intercept_data_0;
intercept_data_0.value = 239; intercept_data_0.value = 239;
intercept_data_0.should_intercept = true; intercept_data_0.should_intercept = true;
...@@ -3056,9 +3060,7 @@ THREADED_TEST(IndexedAllCanReadInterceptor) { ...@@ -3056,9 +3060,7 @@ THREADED_TEST(IndexedAllCanReadInterceptor) {
} }
auto checked = v8::ObjectTemplate::New(isolate); auto checked = v8::ObjectTemplate::New(isolate);
checked->SetAccessCheckCallbacks( checked->SetAccessCheckCallback(SimpleAccessChecker);
SimpleAccessChecker, nullptr,
BuildWrappedObject<AccessCheckData>(isolate, &access_check_data));
context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance()); context->Global()->Set(v8_str("intercepted_0"), intercepted_0->NewInstance());
context->Global()->Set(v8_str("intercepted_1"), intercepted_1->NewInstance()); context->Global()->Set(v8_str("intercepted_1"), intercepted_1->NewInstance());
...@@ -3094,6 +3096,8 @@ THREADED_TEST(IndexedAllCanReadInterceptor) { ...@@ -3094,6 +3096,8 @@ THREADED_TEST(IndexedAllCanReadInterceptor) {
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
} }
CHECK_EQ(9, access_check_data.count); CHECK_EQ(9, access_check_data.count);
g_access_check_data = nullptr;
} }
......
This diff is collapsed.
...@@ -988,10 +988,8 @@ TEST(UseCountObjectGetNotifier) { ...@@ -988,10 +988,8 @@ TEST(UseCountObjectGetNotifier) {
} }
static bool NamedAccessCheckAlwaysAllow(Local<v8::Object> global, static bool NamedAccessCheckAlwaysAllow(Local<v8::Context> accessing_context,
Local<v8::Value> name, Local<v8::Object> accessed_object) {
v8::AccessType type,
Local<Value> data) {
return true; return true;
} }
...@@ -1002,7 +1000,7 @@ TEST(DisallowObserveAccessCheckedObject) { ...@@ -1002,7 +1000,7 @@ TEST(DisallowObserveAccessCheckedObject) {
LocalContext env; LocalContext env;
v8::Local<v8::ObjectTemplate> object_template = v8::Local<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate); v8::ObjectTemplate::New(isolate);
object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL); object_template->SetAccessCheckCallback(NamedAccessCheckAlwaysAllow);
Local<Object> new_instance = Local<Object> new_instance =
object_template->NewInstance( object_template->NewInstance(
v8::Isolate::GetCurrent()->GetCurrentContext()) v8::Isolate::GetCurrent()->GetCurrentContext())
...@@ -1023,7 +1021,7 @@ TEST(DisallowGetNotifierAccessCheckedObject) { ...@@ -1023,7 +1021,7 @@ TEST(DisallowGetNotifierAccessCheckedObject) {
LocalContext env; LocalContext env;
v8::Local<v8::ObjectTemplate> object_template = v8::Local<v8::ObjectTemplate> object_template =
v8::ObjectTemplate::New(isolate); v8::ObjectTemplate::New(isolate);
object_template->SetAccessCheckCallbacks(NamedAccessCheckAlwaysAllow, NULL); object_template->SetAccessCheckCallback(NamedAccessCheckAlwaysAllow);
Local<Object> new_instance = Local<Object> new_instance =
object_template->NewInstance( object_template->NewInstance(
v8::Isolate::GetCurrent()->GetCurrentContext()) v8::Isolate::GetCurrent()->GetCurrentContext())
......
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