static JSBool
XPC_SJOW_CheckAccess(JSContext *cx, JSObject *obj, jsval id,
                     JSAccessMode mode, jsval *vp)
{
  // Prevent setting __proto__ on an XPCSafeJSObjectWrapper
  if ((mode & JSACC_WATCH) == JSACC_PROTO && (mode & JSACC_WRITE)) {
    return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx);
  }

  // Forward to the checkObjectAccess hook in the runtime, if any.
  JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
  if (callbacks && callbacks->checkObjectAccess &&
      !callbacks->checkObjectAccess(cx, obj, id, mode, vp)) {
    return JS_FALSE;
  }

  JSObject *unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    return JS_TRUE;
  }

  // Forward the unsafe object to the checkObjectAccess hook in the
  // runtime too, if any.
  if (callbacks && callbacks->checkObjectAccess &&
      !callbacks->checkObjectAccess(cx, unsafeObj, id, mode, vp)) {
    return JS_FALSE;
  }

  JSClass *clazz = STOBJ_GET_CLASS(unsafeObj);
  return !clazz->checkAccess ||
    clazz->checkAccess(cx, unsafeObj, id, mode, vp);
}
Beispiel #2
0
static JSBool
checkAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
            jsval *vp)
{
  // Forward to the checkObjectAccess hook in the runtime, if any.
  JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
  if (callbacks && callbacks->checkObjectAccess)
    return callbacks->checkObjectAccess(cx, obj, id, mode, vp);
  JS_ReportError(cx, "Security callbacks not defined");
  return JS_FALSE;
}
bool
GlobalObject::isEvalAllowed(JSContext *cx)
{
    Value &v = getSlotRef(EVAL_ALLOWED);
    if (v.isUndefined()) {
        JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);

        /*
         * If there are callbacks, make sure that the CSP callback is installed
         * and that it permits eval(), then cache the result.
         */
        v.setBoolean((!callbacks || !callbacks->contentSecurityPolicyAllows) ||
                     callbacks->contentSecurityPolicyAllows(cx));
    }
    return !v.isFalse();
}
Beispiel #4
0
bool
GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx)
{
    Value &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
    if (v.isUndefined()) {
        JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);

        /*
         * If there are callbacks, make sure that the CSP callback is installed
         * and that it permits runtime code generation, then cache the result.
         */
        v.setBoolean((!callbacks || !callbacks->contentSecurityPolicyAllows) ||
                     callbacks->contentSecurityPolicyAllows(cx));
    }
    return !v.isFalse();
}
Beispiel #5
0
static JSBool
InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
               JSString *filename, uintN lineno, JSErrorReport *report)
{
    JSSecurityCallbacks *callbacks;
    JSCheckAccessOp checkAccess;
    JSErrorReporter older;
    JSExceptionState *state;
    jsval callerid, v;
    JSStackFrame *fp, *fpstop;
    size_t stackDepth, valueCount, size;
    JSBool overflow;
    JSExnPrivate *priv;
    JSStackTraceElem *elem;
    jsval *values;

    JS_ASSERT(OBJ_GET_CLASS(cx, exnObject) == &js_ErrorClass);

    /*
     * Prepare stack trace data.
     *
     * Set aside any error reporter for cx and save its exception state
     * so we can suppress any checkAccess failures.  Such failures should stop
     * the backtrace procedure, not result in a failure of this constructor.
     */
    callbacks = JS_GetSecurityCallbacks(cx);
    checkAccess = callbacks
                  ? callbacks->checkObjectAccess
                  : NULL;
    older = JS_SetErrorReporter(cx, NULL);
    state = JS_SaveExceptionState(cx);

    callerid = ATOM_KEY(cx->runtime->atomState.callerAtom);
    stackDepth = 0;
    valueCount = 0;
    for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) {
        if (fp->fun && fp->argv) {
            v = JSVAL_NULL;
            if (checkAccess &&
                !checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) {
                break;
            }
            valueCount += fp->argc;
        }
        ++stackDepth;
    }
    JS_RestoreExceptionState(cx, state);
    JS_SetErrorReporter(cx, older);
    fpstop = fp;

    size = offsetof(JSExnPrivate, stackElems);
    overflow = (stackDepth > ((size_t)-1 - size) / sizeof(JSStackTraceElem));
    size += stackDepth * sizeof(JSStackTraceElem);
    overflow |= (valueCount > ((size_t)-1 - size) / sizeof(jsval));
    size += valueCount * sizeof(jsval);
    if (overflow) {
        js_ReportAllocationOverflow(cx);
        return JS_FALSE;
    }
    priv = (JSExnPrivate *)cx->malloc(size);
    if (!priv)
        return JS_FALSE;

    /*
     * We initialize errorReport with a copy of report after setting the
     * private slot, to prevent GC accessing a junk value we clear the field
     * here.
     */
    priv->errorReport = NULL;
    priv->message = message;
    priv->filename = filename;
    priv->lineno = lineno;
    priv->stackDepth = stackDepth;

    values = GetStackTraceValueBuffer(priv);
    elem = priv->stackElems;
    for (fp = js_GetTopStackFrame(cx); fp != fpstop; fp = fp->down) {
        if (!fp->fun) {
            elem->funName = NULL;
            elem->argc = 0;
        } else {
            elem->funName = fp->fun->atom
                            ? ATOM_TO_STRING(fp->fun->atom)
                            : cx->runtime->emptyString;
            elem->argc = fp->argc;
            memcpy(values, fp->argv, fp->argc * sizeof(jsval));
            values += fp->argc;
        }
        elem->ulineno = 0;
        elem->filename = NULL;
        if (fp->script) {
            elem->filename = fp->script->filename;
            if (fp->regs)
                elem->ulineno = js_FramePCToLineNumber(cx, fp);
        }
        ++elem;
    }
    JS_ASSERT(priv->stackElems + stackDepth == elem);
    JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);

    exnObject->setPrivate(priv);

    if (report) {
        /*
         * Construct a new copy of the error report struct. We can't use the
         * error report struct that was passed in, because it's allocated on
         * the stack, and also because it may point to transient data in the
         * JSTokenStream.
         */
        priv->errorReport = CopyErrorReport(cx, report);
        if (!priv->errorReport) {
            /* The finalizer realeases priv since it is in the private slot. */
            return JS_FALSE;
        }
    }

    return JS_TRUE;
}