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 */