Changeset 249608 in webkit
- Timestamp:
- Sep 6, 2019 10:42:11 PM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r249597 r249608 1 2019-09-06 Mark Lam <mark.lam@apple.com> 2 3 Harden protection of the Gigacage Config parameters. 4 https://bugs.webkit.org/show_bug.cgi?id=201570 5 <rdar://problem/55134229> 6 7 Reviewed by Saam Barati. 8 9 Just renaming some function names here. 10 11 * assembler/testmasm.cpp: 12 (JSC::testCagePreservesPACFailureBit): 13 * jit/AssemblyHelpers.h: 14 (JSC::AssemblyHelpers::cageConditionally): 15 * jsc.cpp: 16 (jscmain): 17 1 18 2019-09-06 Ross Kirsling <ross.kirsling@sony.com> 2 19 -
trunk/Source/JavaScriptCore/assembler/testmasm.cpp
r249576 r249608 1211 1211 { 1212 1212 #if GIGACAGE_ENABLED 1213 ASSERT(!Gigacage::isDisablingPrimitiveGigacage Disabled());1213 ASSERT(!Gigacage::isDisablingPrimitiveGigacageForbidden()); 1214 1214 auto cage = compile([] (CCallHelpers& jit) { 1215 1215 emitFunctionPrologue(jit); -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r249556 r249608 1589 1589 #if GIGACAGE_ENABLED 1590 1590 if (Gigacage::isEnabled(kind)) { 1591 if (kind != Gigacage::Primitive || Gigacage::isDisablingPrimitiveGigacage Disabled())1591 if (kind != Gigacage::Primitive || Gigacage::isDisablingPrimitiveGigacageForbidden()) 1592 1592 cageWithoutUntagging(kind, storage); 1593 1593 else { -
trunk/Source/JavaScriptCore/jsc.cpp
r249175 r249608 3087 3087 JSC::Wasm::enableFastMemory(); 3088 3088 #endif 3089 Gigacage:: disableDisablingPrimitiveGigacageIfShouldBeEnabled();3089 Gigacage::forbidDisablingPrimitiveGigacage(); 3090 3090 3091 3091 #if PLATFORM(COCOA) -
trunk/Source/WTF/ChangeLog
r249556 r249608 1 2019-09-06 Mark Lam <mark.lam@apple.com> 2 3 Harden protection of the Gigacage Config parameters. 4 https://bugs.webkit.org/show_bug.cgi?id=201570 5 <rdar://problem/55134229> 6 7 Reviewed by Saam Barati. 8 9 Just renaming some function names here. 10 11 * wtf/Gigacage.h: 12 (Gigacage::forbidDisablingPrimitiveGigacage): 13 (Gigacage::isDisablingPrimitiveGigacageForbidden): 14 (Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled): Deleted. 15 (Gigacage::isDisablingPrimitiveGigacageDisabled): Deleted. 16 1 17 2019-09-05 Mark Lam <mark.lam@apple.com> 2 18 -
trunk/Source/WTF/wtf/Gigacage.h
r249556 r249608 50 50 inline void removePrimitiveDisableCallback(void (*)(void*), void*) { } 51 51 52 inline void disableDisablingPrimitiveGigacageIfShouldBeEnabled() { }52 inline void forbidDisablingPrimitiveGigacage() { } 53 53 54 inline bool isDisablingPrimitiveGigacage Disabled() { return false; }54 inline bool isDisablingPrimitiveGigacageForbidden() { return false; } 55 55 inline bool isPrimitiveGigacagePermanentlyEnabled() { return false; } 56 56 inline bool canPrimitiveGigacageBeDisabled() { return true; } -
trunk/Source/WebKit/ChangeLog
r249605 r249608 1 2019-09-06 Mark Lam <mark.lam@apple.com> 2 3 Harden protection of the Gigacage Config parameters. 4 https://bugs.webkit.org/show_bug.cgi?id=201570 5 <rdar://problem/55134229> 6 7 Reviewed by Saam Barati. 8 9 Just renaming a function name here. 10 11 * WebProcess/WebProcess.cpp: 12 1 13 2019-09-06 Wenson Hsieh <wenson_hsieh@apple.com> 2 14 -
trunk/Source/WebKit/WebProcess/WebProcess.cpp
r249603 r249608 221 221 #endif 222 222 223 Gigacage:: disableDisablingPrimitiveGigacageIfShouldBeEnabled();223 Gigacage::forbidDisablingPrimitiveGigacage(); 224 224 } 225 225 -
trunk/Source/bmalloc/ChangeLog
r249588 r249608 1 2019-09-06 Mark Lam <mark.lam@apple.com> 2 3 Harden protection of the Gigacage Config parameters. 4 https://bugs.webkit.org/show_bug.cgi?id=201570 5 <rdar://problem/55134229> 6 7 Reviewed by Saam Barati. 8 9 1. Rename protectGigacageBasePtrs() and unprotectGigacageBasePtrs() to 10 freezeGigacageConfig() and unfreezeGigacageConfig() respectively. 11 12 Also move the alignment check in protectGigacageBasePtrs() into ensureGigacage(). 13 There's no need to check it more than once. 14 15 2. Introduce permanentlyFreezeGigacageConfig() which permanently makes the 16 Config ReadOnly. Once invoked, the Config cannot be made writable again. 17 18 This is made possible by using vm_protect with a true set_maximum argument. 19 We also add a g_gigacageConfig.isPermanentlyFrozen flag that we assert. 20 Note: this permanence is only true for OS(DARWIN) since vm_protect is Mach API. 21 22 3. Rename disableDisablingPrimitiveGigacageIfShouldBeEnabled() to 23 forbidDisablingPrimitiveGigacage() because "disablingDisabling" is a tongue 24 twister. 25 26 Also, we don't want to make it conditional on "IfShouldBeEnabled". We want 27 forbidDisablingPrimitiveGigacage() to be irreversible. It is up to the client 28 to ensure that the Gigacage is already initialized (if possible) before 29 invoking forbidDisablingPrimitiveGigacage(). Conceptually, the forbidding 30 isn't about guaranteeing that the Gigacage is enabled. It only takes away the 31 option to disable it. 32 33 That said, forbidDisablingPrimitiveGigacage() is only invoked by clients that 34 care about keeping the Gigacage enabled. So, it does a sanity check (with an 35 assertion) that if !GIGACAGE_ALLOCATION_CAN_FAIL, then the Gigacage should be 36 have been initialized and enabled before invoking it. 37 38 We also make sure that forbidDisablingPrimitiveGigacage() calls 39 permanentlyFreezeGigacageConfig() unconditionally. It is safe to call it more 40 than once. This guarantees that the Config is permanently frozen after this, 41 even if a bug should inadvertantly set the 42 g_gigacageConfig.disablingPrimitiveGigacageIsForbidden flag before 43 forbidDisablingPrimitiveGigacage() is invoked. 44 45 4. Assert that ensureGigacage() is only called once. 46 47 5. Assert that shouldBeEnabled() is only called once. 48 Also moved its cached result into the Config so that it can be frozen. 49 50 * bmalloc/Gigacage.cpp: 51 (Gigacage::bmalloc::freezeGigacageConfig): 52 (Gigacage::bmalloc::unfreezeGigacageConfig): 53 (Gigacage::bmalloc::permanentlyFreezeGigacageConfig): 54 (Gigacage::bmalloc::UnfreezeGigacageConfigScope::UnfreezeGigacageConfigScope): 55 (Gigacage::bmalloc::UnfreezeGigacageConfigScope::~UnfreezeGigacageConfigScope): 56 (Gigacage::ensureGigacage): 57 (Gigacage::disablePrimitiveGigacage): 58 (Gigacage::verifyGigacageIsEnabled): 59 (Gigacage::forbidDisablingPrimitiveGigacage): 60 (Gigacage::isDisablingPrimitiveGigacageForbidden): 61 (Gigacage::shouldBeEnabled): 62 (Gigacage::bmalloc::protectGigacageBasePtrs): Deleted. 63 (Gigacage::bmalloc::unprotectGigacageBasePtrs): Deleted. 64 (Gigacage::bmalloc::UnprotectGigacageBasePtrsScope::UnprotectGigacageBasePtrsScope): Deleted. 65 (Gigacage::bmalloc::UnprotectGigacageBasePtrsScope::~UnprotectGigacageBasePtrsScope): Deleted. 66 (Gigacage::primitiveGigacageDisabled): Deleted. 67 (Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled): Deleted. 68 (Gigacage::isDisablingPrimitiveGigacageDisabled): Deleted. 69 * bmalloc/Gigacage.h: 70 (Gigacage::isPrimitiveGigacagePermanentlyEnabled): 71 (Gigacage::canPrimitiveGigacageBeDisabled): 72 (Gigacage::forbidDisablingPrimitiveGigacage): 73 (Gigacage::disableDisablingPrimitiveGigacageIfShouldBeEnabled): Deleted. 74 1 75 2019-09-06 Mark Lam <mark.lam@apple.com> 2 76 -
trunk/Source/bmalloc/bmalloc/Gigacage.cpp
r249556 r249608 36 36 #include <mutex> 37 37 38 #if BOS(DARWIN) 39 #include <mach/mach.h> 40 #endif 41 38 42 #if GIGACAGE_ENABLED 39 43 … … 82 86 namespace { 83 87 84 bool s_isDisablingPrimitiveGigacageDisabled; 85 86 void protectGigacageBasePtrs() 87 { 88 // We might only get page size alignment, but that's also the minimum we need. 89 RELEASE_BASSERT(!(reinterpret_cast<size_t>(&g_gigacageConfig) & (vmPageSize() - 1))); 90 mprotect(&g_gigacageConfig, configSizeToProtect, PROT_READ); 91 } 92 93 void unprotectGigacageBasePtrs() 94 { 95 mprotect(&g_gigacageConfig, configSizeToProtect, PROT_READ | PROT_WRITE); 96 } 97 98 class UnprotectGigacageBasePtrsScope { 88 #if BOS(DARWIN) 89 enum { 90 AllowPermissionChangesAfterThis = false, 91 DisallowPermissionChangesAfterThis = true 92 }; 93 #endif 94 95 static void freezeGigacageConfig() 96 { 97 int result; 98 #if BOS(DARWIN) 99 result = vm_protect(mach_task_self(), reinterpret_cast<vm_address_t>(&g_gigacageConfig), configSizeToProtect, AllowPermissionChangesAfterThis, VM_PROT_READ); 100 #else 101 result = mprotect(&g_gigacageConfig, configSizeToProtect, PROT_READ); 102 #endif 103 RELEASE_BASSERT(!result); 104 } 105 106 static void unfreezeGigacageConfig() 107 { 108 RELEASE_BASSERT(!g_gigacageConfig.isPermanentlyFrozen); 109 int result; 110 #if BOS(DARWIN) 111 result = vm_protect(mach_task_self(), reinterpret_cast<vm_address_t>(&g_gigacageConfig), configSizeToProtect, AllowPermissionChangesAfterThis, VM_PROT_READ | VM_PROT_WRITE); 112 #else 113 result = mprotect(&g_gigacageConfig, configSizeToProtect, PROT_READ | PROT_WRITE); 114 #endif 115 RELEASE_BASSERT(!result); 116 } 117 118 static void permanentlyFreezeGigacageConfig() 119 { 120 if (!g_gigacageConfig.isPermanentlyFrozen) { 121 unfreezeGigacageConfig(); 122 g_gigacageConfig.isPermanentlyFrozen = true; 123 } 124 125 // There's no going back now! 126 int result; 127 #if BOS(DARWIN) 128 result = vm_protect(mach_task_self(), reinterpret_cast<vm_address_t>(&g_gigacageConfig), configSizeToProtect, DisallowPermissionChangesAfterThis, VM_PROT_READ); 129 #else 130 result = mprotect(&g_gigacageConfig, configSizeToProtect, PROT_READ); 131 #endif 132 RELEASE_BASSERT(!result); 133 } 134 135 class UnfreezeGigacageConfigScope { 99 136 public: 100 Un protectGigacageBasePtrsScope()137 UnfreezeGigacageConfigScope() 101 138 { 102 un protectGigacageBasePtrs();103 } 104 105 ~Un protectGigacageBasePtrsScope()139 unfreezeGigacageConfig(); 140 } 141 142 ~UnfreezeGigacageConfigScope() 106 143 { 107 protectGigacageBasePtrs();144 freezeGigacageConfig(); 108 145 } 109 146 }; … … 130 167 onceFlag, 131 168 [] { 169 RELEASE_BASSERT(!g_gigacageConfig.ensureGigacageHasBeenCalled); 170 g_gigacageConfig.ensureGigacageHasBeenCalled = true; 171 132 172 if (!shouldBeEnabled()) 133 173 return; 134 174 175 // We might only get page size alignment, but that's also the minimum 176 // alignment we need for freezing the Config. 177 RELEASE_BASSERT(!(reinterpret_cast<size_t>(&g_gigacageConfig) & (vmPageSize() - 1))); 178 135 179 Kind shuffledKinds[NumberOfKinds]; 136 180 for (unsigned i = 0; i < NumberOfKinds; ++i) … … 192 236 vmDeallocatePhysicalPages(base, totalSize); 193 237 g_gigacageConfig.isEnabled = true; 194 protectGigacageBasePtrs();238 freezeGigacageConfig(); 195 239 }); 196 240 } … … 198 242 void disablePrimitiveGigacage() 199 243 { 244 if (g_gigacageConfig.disablingPrimitiveGigacageIsForbidden) 245 fprintf(stderr, "FATAL: Disabling Primitive gigacage is forbidden, but we don't want that in this process.\n"); 246 247 RELEASE_BASSERT(!g_gigacageConfig.disablingPrimitiveGigacageIsForbidden); 248 RELEASE_BASSERT(!g_gigacageConfig.isPermanentlyFrozen); 249 200 250 ensureGigacage(); 201 251 if (!g_gigacageConfig.basePtrs[Primitive]) { … … 210 260 callback.function(callback.argument); 211 261 callbacks.callbacks.shrink(0); 212 Un protectGigacageBasePtrsScope unprotectScope;262 UnfreezeGigacageConfigScope unfreezeScope; 213 263 g_gigacageConfig.basePtrs[Primitive] = nullptr; 214 264 } … … 242 292 } 243 293 244 static void primitiveGigacageDisabled(void*)245 { 246 if (GIGACAGE_ALLOCATION_CAN_FAIL && !isEnabled())247 return;248 249 static bool s_false;250 fprintf(stderr, "FATAL: Primitive gigacage disabled, but we don't want that in this process.\n"); 251 if (!s_false) 252 BCRASH(); 253 } 254 255 void disableDisablingPrimitiveGigacageIfShouldBeEnabled() 256 { 257 if (shouldBeEnabled()) {258 addPrimitiveDisableCallback(primitiveGigacageDisabled, nullptr);259 s_isDisablingPrimitiveGigacageDisabled = true;260 }261 } 262 263 bool isDisablingPrimitiveGigacageDisabled()264 { 265 return s_isDisablingPrimitiveGigacageDisabled;294 static bool verifyGigacageIsEnabled() 295 { 296 bool isEnabled = g_gigacageConfig.isEnabled; 297 for (size_t i = 0; i < NumberOfKinds; ++i) 298 isEnabled = isEnabled && g_gigacageConfig.basePtrs[i]; 299 return isEnabled; 300 } 301 302 void forbidDisablingPrimitiveGigacage() 303 { 304 RELEASE_BASSERT(GIGACAGE_ALLOCATION_CAN_FAIL || verifyGigacageIsEnabled()); 305 if (!g_gigacageConfig.disablingPrimitiveGigacageIsForbidden) { 306 unfreezeGigacageConfig(); 307 g_gigacageConfig.disablingPrimitiveGigacageIsForbidden = true; 308 } 309 permanentlyFreezeGigacageConfig(); 310 RELEASE_BASSERT(isDisablingPrimitiveGigacageForbidden()); 311 } 312 313 BNO_INLINE bool isDisablingPrimitiveGigacageForbidden() 314 { 315 return g_gigacageConfig.disablingPrimitiveGigacageIsForbidden; 266 316 } 267 317 268 318 bool shouldBeEnabled() 269 319 { 270 static bool cached = false;271 320 static std::once_flag onceFlag; 272 321 std::call_once( 273 322 onceFlag, 274 323 [] { 324 RELEASE_BASSERT(!g_gigacageConfig.shouldBeEnabledHasBeenCalled); 325 g_gigacageConfig.shouldBeEnabledHasBeenCalled = true; 326 275 327 bool debugHeapEnabled = Environment::get()->isDebugHeapEnabled(); 276 328 if (debugHeapEnabled) … … 288 340 } 289 341 290 cached = true;342 g_gigacageConfig.shouldBeEnabled = true; 291 343 }); 292 return cached;344 return g_gigacageConfig.shouldBeEnabled; 293 345 } 294 346 … … 296 348 297 349 #endif // GIGACAGE_ENABLED 298 299 -
trunk/Source/bmalloc/bmalloc/Gigacage.h
r249556 r249608 114 114 union { 115 115 struct { 116 // All the fields in this struct should be chosen such that their 117 // initial value is 0 / null / falsy because Config is instantiated 118 // as a global singleton. 119 116 120 bool isEnabled; 121 bool isPermanentlyFrozen; 122 bool disablingPrimitiveGigacageIsForbidden; 123 bool shouldBeEnabled; 124 125 // We would like to just put the std::once_flag for these functions 126 // here, but we can't because std::once_flag has a implicitly-deleted 127 // default constructor. So, we use a boolean instead. 128 bool shouldBeEnabledHasBeenCalled; 129 bool ensureGigacageHasBeenCalled; 130 117 131 void* basePtrs[NumberOfKinds]; 118 132 }; … … 139 153 BEXPORT void removePrimitiveDisableCallback(void (*)(void*), void*); 140 154 141 BEXPORT void disableDisablingPrimitiveGigacageIfShouldBeEnabled();142 143 BEXPORT bool isDisablingPrimitiveGigacage Disabled();144 inline bool isPrimitiveGigacagePermanentlyEnabled() { return isDisablingPrimitiveGigacage Disabled(); }145 inline bool canPrimitiveGigacageBeDisabled() { return !isDisablingPrimitiveGigacage Disabled(); }155 BEXPORT void forbidDisablingPrimitiveGigacage(); 156 157 BEXPORT bool isDisablingPrimitiveGigacageForbidden(); 158 inline bool isPrimitiveGigacagePermanentlyEnabled() { return isDisablingPrimitiveGigacageForbidden(); } 159 inline bool canPrimitiveGigacageBeDisabled() { return !isDisablingPrimitiveGigacageForbidden(); } 146 160 147 161 BINLINE void* basePtr(Kind kind) … … 234 248 template<typename T> BINLINE T* caged(Kind, T* ptr) { return ptr; } 235 249 template<typename T> BINLINE T* cagedMayBeNull(Kind, T* ptr) { return ptr; } 236 BINLINE void disableDisablingPrimitiveGigacageIfShouldBeEnabled() { }250 BINLINE void forbidDisablingPrimitiveGigacage() { } 237 251 BINLINE bool canPrimitiveGigacageBeDisabled() { return false; } 238 252 BINLINE void disablePrimitiveGigacage() { }
Note: See TracChangeset
for help on using the changeset viewer.