tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Principals.h (7325B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 /* JSPrincipals and related interfaces. */
      8 
      9 #ifndef js_Principals_h
     10 #define js_Principals_h
     11 
     12 #include "mozilla/Atomics.h"
     13 
     14 #include <stdint.h>
     15 
     16 #include "jstypes.h"
     17 
     18 #include "js/TypeDecls.h"
     19 
     20 struct JSStructuredCloneReader;
     21 struct JSStructuredCloneWriter;
     22 
     23 struct JSPrincipals {
     24  /* Don't call "destroy"; use reference counting macros below. */
     25  mozilla::Atomic<int32_t, mozilla::SequentiallyConsistent> refcount{0};
     26 
     27 #ifdef JS_DEBUG
     28  /* A helper to facilitate principals debugging. */
     29  uint32_t debugToken = 0;
     30 #endif
     31 
     32  JSPrincipals() = default;
     33 
     34  struct RefCount {
     35    const int32_t value;
     36    constexpr explicit RefCount(int32_t value) : value(value) {}
     37    RefCount(const RefCount&) = delete;
     38  };
     39  /* Initialize a JSPrincipals with the given refcount in a constexpr-compatible
     40   * way. */
     41  explicit constexpr JSPrincipals(RefCount c) : refcount{c.value} {}
     42 
     43  void setDebugToken(int32_t token) {
     44 #ifdef JS_DEBUG
     45    debugToken = token;
     46 #endif
     47  }
     48 
     49  /*
     50   * Write the principals with the given |writer|. Return false on failure,
     51   * true on success.
     52   */
     53  virtual bool write(JSContext* cx, JSStructuredCloneWriter* writer) = 0;
     54 
     55  /*
     56   * Whether the principal corresponds to a System or AddOn Principal.
     57   * Technically this also checks for an ExpandedAddonPrincipal.
     58   */
     59  virtual bool isSystemOrAddonPrincipal() = 0;
     60 
     61  /*
     62   * This is not defined by the JS engine but should be provided by the
     63   * embedding.
     64   */
     65  JS_PUBLIC_API void dump();
     66 };
     67 
     68 extern JS_PUBLIC_API void JS_HoldPrincipals(JSPrincipals* principals);
     69 
     70 extern JS_PUBLIC_API void JS_DropPrincipals(JSContext* cx,
     71                                            JSPrincipals* principals);
     72 
     73 // Return whether the first principal subsumes the second. The exact meaning of
     74 // 'subsumes' is left up to the browser. Subsumption is checked inside the JS
     75 // engine when determining, e.g., which stack frames to display in a backtrace.
     76 typedef bool (*JSSubsumesOp)(JSPrincipals* first, JSPrincipals* second);
     77 
     78 namespace JS {
     79 enum class RuntimeCode { JS, WASM };
     80 enum class CompilationType { DirectEval, IndirectEval, Function, Undefined };
     81 }  // namespace JS
     82 
     83 /*
     84 * Used to check if a CSP instance wants to disable eval() and friends.
     85 * See JSContext::isRuntimeCodeGenEnabled() in vm/JSContext.cpp.
     86 *
     87 * codeString, compilationType, parameterStrings, bodyString, parameterArgs,
     88 * and bodyArg are defined in the "Dynamic Code Brand Checks" spec
     89 * (see https://tc39.es/proposal-dynamic-code-brand-checks).
     90 *
     91 * An Undefined compilationType is used for cases that are not covered by that
     92 * spec and unused parameters are null/empty. Currently, this includes Wasm
     93 * (only check if compilation is enabled) and ShadowRealmEval (only check
     94 * codeString).
     95 *
     96 * `outCanCompileStrings` is set to false if this callback prevents the
     97 * execution/compilation of the code and to true otherwise.
     98 *
     99 * Return false on failure, true on success. The |outCanCompileStrings|
    100 * parameter should not be modified in case of failure.
    101 */
    102 typedef bool (*JSCSPEvalChecker)(
    103    JSContext* cx, JS::RuntimeCode kind, JS::Handle<JSString*> codeString,
    104    JS::CompilationType compilationType,
    105    JS::Handle<JS::StackGCVector<JSString*>> parameterStrings,
    106    JS::Handle<JSString*> bodyString,
    107    JS::Handle<JS::StackGCVector<JS::Value>> parameterArgs,
    108    JS::Handle<JS::Value> bodyArg, bool* outCanCompileStrings);
    109 
    110 /*
    111 * Provide a string of code from an Object argument, to be used by eval.
    112 * See JSContext::getCodeForEval() in vm/JSContext.cpp as well as
    113 * https://tc39.es/proposal-dynamic-code-brand-checks/#sec-hostgetcodeforeval
    114 *
    115 * `code` is the JavaScript object passed by the user.
    116 * `outCode` is the JavaScript string to be actually executed, with nullptr
    117 *  meaning NO-CODE.
    118 *
    119 * Return false on failure, true on success. The |outCode| parameter should not
    120 * be modified in case of failure.
    121 */
    122 typedef bool (*JSCodeForEvalOp)(JSContext* cx, JS::HandleObject code,
    123                                JS::MutableHandle<JSString*> outCode);
    124 
    125 struct JSSecurityCallbacks {
    126  JSCSPEvalChecker contentSecurityPolicyAllows;
    127  JSCodeForEvalOp codeForEvalGets;
    128  JSSubsumesOp subsumes;
    129 };
    130 
    131 extern JS_PUBLIC_API void JS_SetSecurityCallbacks(
    132    JSContext* cx, const JSSecurityCallbacks* callbacks);
    133 
    134 extern JS_PUBLIC_API const JSSecurityCallbacks* JS_GetSecurityCallbacks(
    135    JSContext* cx);
    136 
    137 /*
    138 * Code running with "trusted" principals will be given a deeper stack
    139 * allocation than ordinary scripts. This allows trusted script to run after
    140 * untrusted script has exhausted the stack. This function sets the
    141 * runtime-wide trusted principal.
    142 *
    143 * This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals).
    144 * Instead, the caller must ensure that the given principals stays valid for as
    145 * long as 'cx' may point to it. If the principals would be destroyed before
    146 * 'cx', JS_SetTrustedPrincipals must be called again, passing nullptr for
    147 * 'prin'.
    148 */
    149 extern JS_PUBLIC_API void JS_SetTrustedPrincipals(JSContext* cx,
    150                                                  JSPrincipals* prin);
    151 
    152 typedef void (*JSDestroyPrincipalsOp)(JSPrincipals* principals);
    153 
    154 /*
    155 * Initialize the callback that is called to destroy JSPrincipals instance
    156 * when its reference counter drops to zero. The initialization can be done
    157 * only once per JS runtime.
    158 */
    159 extern JS_PUBLIC_API void JS_InitDestroyPrincipalsCallback(
    160    JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals);
    161 
    162 /*
    163 * Read a JSPrincipals instance from the given |reader| and initialize the out
    164 * paratemer |outPrincipals| to the JSPrincipals instance read.
    165 *
    166 * Return false on failure, true on success. The |outPrincipals| parameter
    167 * should not be modified if false is returned.
    168 *
    169 * The caller is not responsible for calling JS_HoldPrincipals on the resulting
    170 * JSPrincipals instance, the JSReadPrincipalsOp must increment the refcount of
    171 * the resulting JSPrincipals on behalf of the caller.
    172 */
    173 using JSReadPrincipalsOp = bool (*)(JSContext* cx,
    174                                    JSStructuredCloneReader* reader,
    175                                    JSPrincipals** outPrincipals);
    176 
    177 /*
    178 * Initialize the callback that is called to read JSPrincipals instances from a
    179 * buffer. The initialization can be done only once per JS runtime.
    180 */
    181 extern JS_PUBLIC_API void JS_InitReadPrincipalsCallback(
    182    JSContext* cx, JSReadPrincipalsOp read);
    183 
    184 namespace JS {
    185 
    186 class MOZ_RAII AutoHoldPrincipals {
    187  JSContext* cx_;
    188  JSPrincipals* principals_ = nullptr;
    189 
    190 public:
    191  explicit AutoHoldPrincipals(JSContext* cx, JSPrincipals* principals = nullptr)
    192      : cx_(cx) {
    193    reset(principals);
    194  }
    195 
    196  ~AutoHoldPrincipals() { reset(nullptr); }
    197 
    198  void reset(JSPrincipals* principals) {
    199    if (principals) {
    200      JS_HoldPrincipals(principals);
    201    }
    202    if (principals_) {
    203      JS_DropPrincipals(cx_, principals_);
    204    }
    205    principals_ = principals;
    206  }
    207 
    208  JSPrincipals* get() const { return principals_; }
    209 };
    210 
    211 }  // namespace JS
    212 
    213 #endif /* js_Principals_h */