Submitted By: Douglas R. Reno Date: 2020-11-10 Initial Package Version: 2.53.4 Origin: Upstream + Self (modified to fit this codebase) Upstream Status: Not Applied Description: Fixes CVE-2020-26950, a 0day vulnerability in Seamonkey, MozJS, Firefox, and Thunderbird. This patch was heavily modified to fit the Seamonkey codebase. The following are relevant URLs: https://www.mozilla.org/en-US/security/advisories/mfsa2020-49/ https://hg.mozilla.org/releases/mozilla-esr78/rev/22b8bef3c436a4d36b586804f342928e1ab11e51 https://us-cert.cisa.gov/ncas/current-activity/2020/11/10/mozilla-releases-security-updates-firefox-firefox-esr-and diff -Naurp seamonkey-2.53.4.orig/mozilla/js/src/jit/IonBuilder.cpp seamonkey-2.53.4/mozilla/js/src/jit/IonBuilder.cpp --- seamonkey-2.53.4.orig/mozilla/js/src/jit/IonBuilder.cpp 2020-04-01 06:01:50.000000000 -0500 +++ seamonkey-2.53.4/mozilla/js/src/jit/IonBuilder.cpp 2020-11-10 14:17:11.795757359 -0600 @@ -4848,35 +4848,24 @@ IonBuilder::createCallObject(MDefinition } MDefinition* -IonBuilder::createThisScripted(MDefinition* callee, MDefinition* newTarget) -{ +IonBuilder::createThisScripted(MDefinition* callee, + MDefinition* newTarget) { // Get callee.prototype. // // This instruction MUST be idempotent: since it does not correspond to an // explicit operation in the bytecode, we cannot use resumeAfter(). // Getters may not override |prototype| fetching, so this operation is indeed idempotent. - // - First try an idempotent property cache. - // - Upon failing idempotent property cache, we can't use a non-idempotent cache, - // therefore we fallback to CallGetProperty - // - // Note: both CallGetProperty and GetPropertyCache can trigger a GC, - // and thus invalidation. - MInstruction* getProto; - if (!invalidatedIdempotentCache()) { - MConstant* id = constant(StringValue(names().prototype)); - MGetPropertyCache* getPropCache = MGetPropertyCache::New(alloc(), newTarget, id, - /* monitored = */ false); - getPropCache->setIdempotent(); - getProto = getPropCache; - } else { - MCallGetProperty* callGetProp = MCallGetProperty::New(alloc(), newTarget, names().prototype); - callGetProp->setIdempotent(); - getProto = callGetProp; - } - current->add(getProto); + // Note: GetPropertyCache can trigger a GC, and thus invalidation. + MConstant* id = constant(StringValue(names().prototype)); + MGetPropertyCache* getPropCache = + MGetPropertyCache::New(alloc(), newTarget, id, + /* monitored = */ false); + getPropCache->setIdempotent(); + current->add(getPropCache); // Create this from prototype - MCreateThisWithProto* createThis = MCreateThisWithProto::New(alloc(), callee, newTarget, getProto); + MCreateThisWithProto* createThis = + MCreateThisWithProto::New(alloc(), callee, newTarget, getPropCache); current->add(createThis); return createThis; diff -Naurp seamonkey-2.53.4.orig/mozilla/js/src/jit/IonIC.cpp seamonkey-2.53.4/mozilla/js/src/jit/IonIC.cpp --- seamonkey-2.53.4.orig/mozilla/js/src/jit/IonIC.cpp 2020-08-10 06:30:34.000000000 -0500 +++ seamonkey-2.53.4/mozilla/js/src/jit/IonIC.cpp 2020-11-10 15:21:27.465714885 -0600 @@ -162,6 +162,16 @@ IonGetPropertyIC::update(JSContext* cx, if (outerScript->hasIonScript()) Invalidate(cx, outerScript); + + // IonBuilder::createScriptedThis does not use InvalidedIdempotentCache + // flag so prevent bailout-loop by disabling Ion for the script. + MOZ_ASSERT(ic->kind() == CacheKind::GetProp); + if (idVal.toString()->asAtom().asPropertyName() == cx->names().prototype) { + if (val.isObject() && val.toObject().is()) { + return Method_Skipped; + } + } + // We will redo the potentially effectful lookup in Baseline. return true; }