Skip to content

Commit

Permalink
[CVE-2017-11889] UaF On the latest Patch - Qihoo 360
Browse files Browse the repository at this point in the history
This change addresses a UAF that occurs when jitted code tries to index
into a detached ArrayBuffer.
The POC involves the convergence of JITing
- a virtual type buffer (a certain performant type buffer that meets
certain criteria)
- A proxy object whose setter can cause the type buffer to be detached
With this, it's possible to JIT code that indexes into the buffer
without any checks. Thus, it's possible to index into the freed memory
that backed the ArrayBuffer.

The fix is to make sure that any call before a virtual ArrayBuffer
access has a bailout to detect and protect against this assertion.
  • Loading branch information
Thomas Moore (CHAKRA) authored and MikeHolman committed Dec 7, 2017
1 parent fde1643 commit 66b9abb
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 2 deletions.
6 changes: 4 additions & 2 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12946,7 +12946,9 @@ GlobOpt::ProcessValueKills(IR::Instr *const instr)
Assert(kills.KillsTypedArrayHeadSegmentLengths());

// - Calls need to kill the value types of values in the following list. For instance, calls can transform a JS array
// into an ES5 array, so any definitely-array value types need to be killed. Update the value types.
// into an ES5 array, so any definitely-array value types need to be killed. Also, VirtualTypeArrays do not have
// bounds checks; this can be problematic if the array is detached, so check to ensure that it is a virtual array.
// Update the value types to likley to ensure a bailout that asserts Array type is generated.
// - Calls also need to kill typed array head segment lengths. A typed array's array buffer may be transferred to a web
// worker, in which case the typed array's length is set to zero.
for(auto it = valuesToKillOnCalls->GetIterator(); it.IsValid(); it.MoveNext())
Expand All @@ -12956,7 +12958,7 @@ GlobOpt::ProcessValueKills(IR::Instr *const instr)
Assert(
valueInfo->IsArrayOrObjectWithArray() ||
valueInfo->IsOptimizedTypedArray() && valueInfo->AsArrayValueInfo()->HeadSegmentLengthSym());
if(valueInfo->IsArrayOrObjectWithArray())
if (valueInfo->IsArrayOrObjectWithArray() || valueInfo->IsOptimizedVirtualTypedArray())
{
ChangeValueType(nullptr, value, valueInfo->Type().ToLikely(), false);
continue;
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/ValueInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ class ValueInfo : protected ValueType
using ValueType::IsLikelyTypedArray;

using ValueType::IsOptimizedTypedArray;
using ValueType::IsOptimizedVirtualTypedArray;
using ValueType::IsLikelyOptimizedTypedArray;
using ValueType::IsLikelyOptimizedVirtualTypedArray;

Expand Down
5 changes: 5 additions & 0 deletions lib/Runtime/Language/ValueType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,11 @@ bool ValueType::IsOptimizedTypedArray() const
return IsObject() && ((GetObjectType() >= ObjectType::Int8Array && GetObjectType() <= ObjectType::Float64MixedArray));
}

bool ValueType::IsOptimizedVirtualTypedArray() const
{
return IsObject() && (GetObjectType() >= ObjectType::Int8VirtualArray && GetObjectType() <= ObjectType::Float64VirtualArray);
}

bool ValueType::IsLikelyOptimizedTypedArray() const
{
return IsLikelyObject() && ((GetObjectType() >= ObjectType::Int8Array && GetObjectType() <= ObjectType::Float64MixedArray));
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Language/ValueType.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ class ValueType
bool IsTypedIntOrFloatArray() const;

bool IsOptimizedTypedArray() const;
bool IsOptimizedVirtualTypedArray() const;
bool IsLikelyOptimizedTypedArray() const;
bool IsLikelyOptimizedVirtualTypedArray() const;

Expand Down

0 comments on commit 66b9abb

Please sign in to comment.