Bug 1478036: Ensure that inproc nop-space patches use atomic writes; r=handyman

--HG--
extra : rebase_source : 9542cd801a8d4589e47d161c17c92552db468e7a
This commit is contained in:
Aaron Klotz 2018-07-26 15:34:48 -06:00
parent b231c55815
commit 9669df786c
3 changed files with 60 additions and 4 deletions

View File

@ -122,6 +122,14 @@ public:
return true;
}
#if defined(_M_IX86)
bool WriteAtomic(void* aDestPtr, const uint16_t aValue) const
{
*static_cast<uint16_t*>(aDestPtr) = aValue;
return true;
}
#endif // defined(_M_IX86)
bool Protect(void* aVAddress, size_t aSize, uint32_t aProtFlags,
uint32_t* aPrevProtFlags) const
{

View File

@ -51,8 +51,7 @@ public:
}
// mov edi, edi
fn.WriteShort(0xff8b);
fn.Commit();
fn.CommitAndWriteShort(0xff8b);
}
mPatchedFns.clear();
@ -206,8 +205,7 @@ public:
sizeof(uint16_t));
// Short jump up into our long jump.
writableFn.WriteShort(0xF9EB); // jmp $-5
return writableFn.Commit();
return writableFn.CommitAndWriteShort(0xF9EB); // jmp $-5
}
};

View File

@ -177,6 +177,9 @@ public:
}
mMMPolicy.FlushInstructionCache();
mStartWriteOffset += mLocalBytes.length();
mLocalBytes.clear();
return true;
}
@ -228,6 +231,53 @@ public:
mOffset += sizeof(uint16_t);
}
#if defined(_M_IX86)
private:
template <typename T>
bool CommitAndWriteShortInternal(const T& aMMPolicy, void* aDest, uint16_t aValue);
template <>
bool CommitAndWriteShortInternal<MMPolicyInProcess>(const MMPolicyInProcess& aMMPolicy,
void* aDest, uint16_t aValue)
{
return aMMPolicy.WriteAtomic(aDest, aValue);
}
template <>
bool CommitAndWriteShortInternal<MMPolicyOutOfProcess>(const MMPolicyOutOfProcess& aMMPolicy,
void* aDest, uint16_t aValue)
{
return aMMPolicy.Write(aDest, &aValue, sizeof(uint16_t));
}
public:
/**
* Commits any dirty writes, and then writes a short, atomically if possible.
* This call may succeed in both inproc and outproc cases, but atomicity
* is only guaranteed in the inproc case.
*/
bool CommitAndWriteShort(const uint16_t aValue)
{
// First, commit everything that has been written until now
if (!Commit()) {
return false;
}
// Now immediately write the short, atomically if inproc
bool ok = CommitAndWriteShortInternal(mMMPolicy,
reinterpret_cast<void*>(mFunc +
mStartWriteOffset),
aValue);
if (!ok) {
return false;
}
mMMPolicy.FlushInstructionCache();
mStartWriteOffset += sizeof(uint16_t);
return true;
}
#endif // defined(_M_IX86)
void WriteDisp32(const uintptr_t aAbsTarget)
{
intptr_t diff = static_cast<intptr_t>(aAbsTarget) -