Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Cross origin wrappers #16501

Closed
wants to merge 13 commits into from

added wrapper selection and subsumes logic

  • Loading branch information
avadacatavra committed Apr 25, 2017
commit 3577d1ff94d8568db22a387f84c42a0f817f2edc
@@ -141,7 +141,9 @@ pub unsafe fn create_global_object(

let x = private.clone() as *const Window;
let obj = &*x;
let mut principal = CreateServoJSPrincipal(Box::into_raw(obj.origin()) as *const ::libc::c_void);
let mut principal = CreateServoJSPrincipal(Box::into_raw(obj.origin()) as *const ::libc::c_void,
None,
None);

rval.set(JS_NewGlobalObject(cx,
class,
@@ -17,10 +17,11 @@ use heapsize::HeapSizeOf;
use js;
use js::JS_CALLEE;
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
use js::glue::{GetCrossCompartmentWrapper, WrapperNew};
use js::glue::getPrincipalOrigin;
use js::glue::{GetCrossCompartmentWrapper, GetSecurityWrapper, WrapperNew};
use js::glue::{GetPrincipalOrigin, CreateWrapperProxyHandler, UncheckedUnwrapObject};
use js::glue::{RUST_FUNCTION_VALUE_TO_JITINFO, RUST_JSID_IS_INT, RUST_JSID_IS_STRING};
use js::glue::{RUST_JSID_TO_INT, RUST_JSID_TO_STRING, UnwrapObject};
use js::jsapi::{JS_GetClass, JS_GetCompartmentPrincipals, JSPrincipals};
use js::jsapi::{CallArgs, DOMCallbacks, GetGlobalForObjectCrossCompartment};
use js::jsapi::{HandleId, HandleObject, HandleValue, Heap, JSAutoCompartment, JSContext};
use js::jsapi::{JSJitInfo, JSObject, JSTracer, JSWrapObjectCallbacks};
@@ -30,15 +31,16 @@ use js::jsapi::{JS_GetProperty, JS_GetPrototype, JS_GetReservedSlot, JS_HasPrope
use js::jsapi::{JS_HasPropertyById, JS_IsExceptionPending, JS_IsGlobalObject};
use js::jsapi::{JS_ResolveStandardClass, JS_SetProperty, ToWindowProxyIfWindow};
use js::jsapi::{JS_StringHasLatin1Chars, MutableHandleValue, ObjectOpResult};
use js::jsapi::JSPrincipals;
use js::jsval::{JSVal, UndefinedValue};
use js::rust::{GCMethods, ToString, get_object_class, is_dom_class};
use js::rust::{get_context_compartment, get_object_compartment};
use libc;
use servo_url::MutableOrigin;
use std::ffi::CString;
use std::ffi::{CString, CStr};
use std::os::raw::{c_char, c_void};
use std::ptr;
use std::slice;
use std::str;

/// Proxy handler for a WindowProxy.
pub struct WindowProxyHandler(pub *const libc::c_void);
@@ -50,15 +52,104 @@ impl HeapSizeOf for WindowProxyHandler {
}
}

struct ServoJSPrincipal(*mut JSPrincipals);
//TODO make principal.rs

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

Yep.

pub struct ServoJSPrincipal(*mut JSPrincipals);

impl ServoJSPrincipal {
pub unsafe fn origin(&self) -> MutableOrigin {
let origin = getPrincipalOrigin(self.0) as *mut MutableOrigin;
let origin = GetPrincipalOrigin(self.0) as *mut MutableOrigin;
(*origin).clone()
}
}

// avadacatavra: destroy will need to retrieved the boxed origin pointer, turn it back into a box and allow it to be freed

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

We'll want to remove this.

pub unsafe fn destroy_servo_jsprincipal(principal: &mut ServoJSPrincipal) {
let origin = GetPrincipalOrigin(principal.0) as *mut Box<MutableOrigin>;

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

Casting to a *mut Box is incorrect; we need *mut MutableOrigin here so we can use from_raw and cause its destructor to run.

}

#[derive(Debug, PartialEq)]
enum WrapperType {
CrossCompartment,
CrossOrigin,
Opaque,
}

#[derive(Debug, PartialEq)]
enum CrossOriginObjectType {
CrossOriginWindow,
CrossOriginLocation,
CrossOriginOpaque,
}

unsafe fn identify_cross_origin_object(obj: HandleObject) -> CrossOriginObjectType {
let obj = UncheckedUnwrapObject(obj.get(), /* stopAtWindowProxy = */ 0);
let obj_class = JS_GetClass(obj);
let name = str::from_utf8(CStr::from_ptr((*obj_class).name).to_bytes()).unwrap().to_owned();
match &*name {
"Location" => CrossOriginObjectType::CrossOriginLocation,
"Window" => CrossOriginObjectType::CrossOriginWindow,
_ => CrossOriginObjectType::CrossOriginOpaque,

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member
let name = CStr::from_ptr((*obj_class).name).to_bytes();
match name {
    b"Location" => ...,
    b"Window" => ...,
    _ => ...,
}
}
}

unsafe fn target_subsumes_obj(cx: *mut JSContext, obj: HandleObject) -> bool {

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

Let's call this obj_subsumes_current_compartment.

//step 1 get compartment
let obj_c = get_object_compartment(obj.get());
let ctx_c = get_context_compartment(cx);

//step 2 get principals
let obj_p = JS_GetCompartmentPrincipals(obj_c);
let ctx_p = JS_GetCompartmentPrincipals(ctx_c);

//TODO determine what subsumes check is sufficient
subsumes(obj_p, ctx_p)
//step 3 check document.domain

//step 4

//step 5 if nested, get base uri

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

We have no nested URIs in Servo.


//step 6 compare schemes. if files, return false unless identical

//step 7 compare hosts

//step 8 compare ports
//false

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

Since these are all covered by subsumes afaict, we don't need to leave references to them here.

}

//TODO check what type of wrapper we should use to disallow any access
unsafe fn get_opaque_wrapper() -> *const ::libc::c_void {
GetSecurityWrapper()
}

// FIXME use an actual XOW
unsafe fn get_cross_origin_wrapper() -> *const ::libc::c_void {
GetSecurityWrapper()
}

//TODO is same_origin_domain equivalent to subsumes for our purposes
pub unsafe extern fn subsumes(obj: *mut JSPrincipals, other: *mut JSPrincipals) -> bool {
let obj = &ServoJSPrincipal(obj);
let other = &ServoJSPrincipal(other);

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

The &s aren't necessary here.

let obj_origin = obj.origin();
let other_origin = other.origin();
obj_origin.same_origin_domain(&other_origin)
}

unsafe fn select_wrapper(cx: *mut JSContext, obj: HandleObject) -> *const libc::c_void {
let security_wrapper = !target_subsumes_obj(cx, obj);
if !security_wrapper {

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

This will be easier to reason about as if target_subsumes_obj(cx, obj) {.

return GetCrossCompartmentWrapper()
};

if identify_cross_origin_object(obj) != CrossOriginObjectType::CrossOriginOpaque {
return get_cross_origin_wrapper()
};

get_opaque_wrapper()
}


#[derive(JSTraceable, HeapSizeOf)]
/// Static data associated with a global object.
pub struct GlobalStaticData {
@@ -387,7 +478,8 @@ unsafe extern "C" fn wrap(cx: *mut JSContext,
-> *mut JSObject {
// FIXME terrible idea. need security wrappers
// https://github.com/servo/servo/issues/2382

This comment has been minimized.

Copy link
@jdm

jdm May 1, 2017

Member

These comments can go away.

WrapperNew(cx, obj, GetCrossCompartmentWrapper(), ptr::null(), false)
let wrapper = select_wrapper(cx, obj);
WrapperNew(cx, obj, wrapper, ptr::null(), false)
}

unsafe extern "C" fn pre_wrap(cx: *mut JSContext,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.