| Index: native_client_sdk/doc_generated/reference/sandbox_internals/x86-64-sandbox.html
|
| diff --git a/native_client_sdk/doc_generated/reference/sandbox_internals/x86-64-sandbox.html b/native_client_sdk/doc_generated/reference/sandbox_internals/x86-64-sandbox.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..91d1b4614bb472e47a8d7c3523e117fe21dbeb56
|
| --- /dev/null
|
| +++ b/native_client_sdk/doc_generated/reference/sandbox_internals/x86-64-sandbox.html
|
| @@ -0,0 +1,323 @@
|
| +{{+bindTo:partials.standard_nacl_article}}
|
| +
|
| +<section id="nacl-sfi-model-on-x86-64-systems">
|
| +<span id="x86-64-sandbox"></span><h1 id="nacl-sfi-model-on-x86-64-systems"><span id="x86-64-sandbox"></span>NaCl SFI model on x86-64 systems</h1>
|
| +<div class="contents local" id="contents" style="display: none">
|
| +<ul class="small-gap">
|
| +<li><a class="reference internal" href="#summary" id="id5">Summary</a></li>
|
| +<li><a class="reference internal" href="#binary-format" id="id6">Binary Format</a></li>
|
| +<li><a class="reference internal" href="#runtime-invariants" id="id7">Runtime Invariants</a></li>
|
| +<li><a class="reference internal" href="#text-segment-rules" id="id8">Text Segment Rules</a></li>
|
| +<li><a class="reference internal" href="#list-of-pseudo-instructions" id="id9">List of Pseudo-instructions</a></li>
|
| +</ul>
|
| +
|
| +</div><section id="summary">
|
| +<h2 id="summary">Summary</h2>
|
| +<p>This document addresses the details of the Software Fault Isolation
|
| +(SFI) model for executable code that can be run in Native Client on an
|
| +x86-64 system. An overview of this model can be found in the paper:
|
| +<a class="reference external" href="https://research.google.com/pubs/archive/35649.pdf">Adapting Software Fault Isolation to Contemporary CPU Architectures</a>.
|
| +The primary focus of the SFI model is a Windows x86-64 system but the
|
| +same techniques can be applied to run identical x86-64 binaries on
|
| +other x86-64 systems such as Linux, Mac, FreeBSD, etc, so the
|
| +description of the SFI model tries to abstract away system
|
| +dependencies when possible.</p>
|
| +<p>Please note: throughout this document we use the AT&T notation for
|
| +assembler syntax, in which the target operand appears last, e.g. <code>mov
|
| +src, dst</code>.</p>
|
| +</section><section id="binary-format">
|
| +<h2 id="binary-format">Binary Format</h2>
|
| +<p>The format of Native Client executable binaries is identical to the
|
| +x86-64 ELF binary format (<a class="reference external" href="http://en.wikipedia.org/wiki/Executable_and_Linkable_Format">[0]</a>, <a class="reference external" href="http://www.sco.com/developers/devspecs/gabi41.pdf">[1]</a>, <a class="reference external" href="http://www.sco.com/developers/gabi/latest/contents.html">[2]</a>, <a class="reference external" href="http://downloads.openwatcom.org/ftp/devel/docs/elf-64-gen.pdf">[3]</a>) for
|
| +Linux or BSD with a few extra requirements. The additional rules that
|
| +a Native Client ELF binary must follow are:</p>
|
| +<ul class="small-gap">
|
| +<li>The ELF magic OS ABI field must be 123.</li>
|
| +<li>The ELF magic OS ABI VERSION field must be 5.</li>
|
| +<li>The ELF e_flags field must be 0x200000 (32-byte alignment).</li>
|
| +<li>There must be exactly one PT_LOAD text segment. It must begin at
|
| +0x20000 (128 kB) and be marked RX (no W). The contents of the text
|
| +segment must follow <a class="reference internal" href="#x86-64-text-segment-rules"><em>Text Segment Rules</em></a>.</li>
|
| +<li>There can be at most one PT_LOAD data segment marked R.</li>
|
| +<li>There can be at most one PT_LOAD data segment marked RW.</li>
|
| +<li>There can be at most one PT_GNU_STACK segment. It must be marked RW.</li>
|
| +<li>All segments must end before limit address (4 GiB).</li>
|
| +</ul>
|
| +</section><section id="runtime-invariants">
|
| +<h2 id="runtime-invariants">Runtime Invariants</h2>
|
| +<p>To ensure fault isolation at runtime, the system must maintain a
|
| +number of runtime <em>invariants</em> across the lifetime of the running
|
| +program. Both the <em>Validator</em> and the <em>Service Runtime</em> are
|
| +responsible for maintaining the invariants. See the paper for the
|
| +rationale for the invariants:</p>
|
| +<ul class="small-gap">
|
| +<li><code>RIP</code> always points to valid instruction boundary (the validator must
|
| +ensure this with direct jumps and direct calls).</li>
|
| +<li><code>R15</code> (aka <code>RBASE</code> and <code>RZP</code>) is never modified by code (the
|
| +validator must ensure this). Low 32 bits of <code>RZP</code> are all zero
|
| +(loader must ensure this).</li>
|
| +<li><code>RIP</code>, <code>RBP</code> and <code>RSP</code> are always in the <strong>safe zone</strong>: between
|
| +<code>R15</code> and <code>R15+4GiB</code>.</li>
|
| +</ul>
|
| +<blockquote>
|
| +<div><ul class="small-gap">
|
| +<li>Exception: <code>RSP</code> and <code>RBP</code> are allowed to be in the range of
|
| +<code>0..4GiB</code> inside <em>pseudo-instructions</em>: <code>naclrestbp</code>,
|
| +<code>naclrestsp</code>, <code>naclspadj</code>, <code>naclasp</code>, <code>naclssp</code>.</li>
|
| +</ul>
|
| +</div></blockquote>
|
| +<ul class="small-gap">
|
| +<li>84GiB are allocated for NaCl module (i.e. <strong>untrusted region</strong>):</li>
|
| +</ul>
|
| +<blockquote>
|
| +<div><ul class="small-gap">
|
| +<li><code>R15-40GiB..R15</code> and <code>R15+4GIB..R15+44GiB</code> are buffer zones with
|
| +PROT_NONE flags.</li>
|
| +<li>The 4GB <em>safe zone</em> has pages with either PROT_WRITE or PROT_EXEC
|
| +but must not have PROT_WRITE+PROT_EXEC pages.</li>
|
| +<li>All executable code in PROT_EXEC pages is validatable and
|
| +guaranteed to obey the invariant.</li>
|
| +</ul>
|
| +</div></blockquote>
|
| +<ul class="small-gap">
|
| +<li>Trampoline/springboard code is mapped to a non-writable region in
|
| +the <em>untrusted 84GB region</em>; each trampoline/springboard is 32-byte
|
| +aligned and fits within a single <em>bundle</em>.</li>
|
| +<li>The OS must not put any internal structures/code into the untrusted
|
| +region at any time (not using OS dynamic linker, etc)</li>
|
| +</ul>
|
| +</section><section id="text-segment-rules">
|
| +<span id="x86-64-text-segment-rules"></span><h2 id="text-segment-rules"><span id="x86-64-text-segment-rules"></span>Text Segment Rules</h2>
|
| +<ul class="small-gap">
|
| +<li>The validation process must ensure that the text segment complies
|
| +with the following rules. The validation process must complete
|
| +successfully strictly before executing any instruction of the
|
| +untrusted code.</li>
|
| +<li>The following instructions are illegal and must be rejected by the
|
| +validator (the list is not exhaustive as the validator uses a
|
| +whiteist, not a blacklist; this means there is a large but finite
|
| +list of instructions the validator allows, not a small list of
|
| +instructions the validator rejects):</li>
|
| +</ul>
|
| +<blockquote>
|
| +<div><ul class="small-gap">
|
| +<li>any privileged instructions</li>
|
| +<li><code>mov</code> to/from segment registers</li>
|
| +<li><code>int</code></li>
|
| +<li><code>pusha</code>/<code>popa</code> (not dangerous but not needed for GCC)</li>
|
| +</ul>
|
| +</div></blockquote>
|
| +<ul class="small-gap">
|
| +<li>There must be space for at least 32 bytes after the text segment and
|
| +before the next segment in ELF (towards higher addresses) that ends
|
| +strictly at a 64K boundary (a minimum page size for untrusted
|
| +code). This space will be padded with HLT instructions as part of
|
| +the validation process, along with the optional 64K page.</li>
|
| +<li>Neither instructions nor <em>pseudo-instructions</em> are permitted to span
|
| +a 32-byte boundary.</li>
|
| +<li>The ELF entry address must be 32-byte aligned.</li>
|
| +<li>Direct <code>CALL</code>/<code>JUMP</code> targets:</li>
|
| +</ul>
|
| +<blockquote>
|
| +<div><ul class="small-gap">
|
| +<li>must point to a valid instruction boundary</li>
|
| +<li>must not point into a <em>pseudo-instruction</em></li>
|
| +<li>must not point between a <em>restricted register</em> (see below for
|
| +definition) producer instruction and its corresponding restricted
|
| +register consumer instruction.</li>
|
| +</ul>
|
| +</div></blockquote>
|
| +<ul class="small-gap">
|
| +<li><code>CALL</code> instructions must be 5 bytes before a 32-byte boundary, so
|
| +that the return address will be 32-byte aligned.</li>
|
| +<li>Indirect call targets must be 32-byte aligned. Instead of indirect
|
| +<code>CALL</code>/<code>JMP</code> x, use <code>nacljmp</code> and <code>naclcall</code> (see below for
|
| +definitions of these <em>pseudo-instructions</em>)</li>
|
| +<li>All instructions that <strong>read</strong> or <strong>write</strong> from/to memory must use
|
| +one of the four registers <code>RZP</code>, <code>RIP</code>, <code>RBP</code> or <code>RSP</code> as a
|
| +base, restricted (see below) register index (multiplied by 0, 1, 2,
|
| +4 or 8) and constant displacement (optional).</li>
|
| +</ul>
|
| +<blockquote>
|
| +<div><ul class="small-gap">
|
| +<li><p class="first">Exception to this rule: string instructions are allowed if used in
|
| +following sequences (the sequences should not cross <em>bundle</em>
|
| +boundaries; segment overrides are disallowed):</p>
|
| +<pre>
|
| + mov %edi, %edi
|
| + lea (%rZP,%rdi),%rdi
|
| + [rep] stos ; (other string instructions can be used here)
|
| +</pre>
|
| +<p>Note: this is identical to the <em>pseudo-instruction</em>: <code>[rep] stos
|
| +%?ax, %nacl:(%rdi),%rZP</code></p>
|
| +</li>
|
| +</ul>
|
| +</div></blockquote>
|
| +<ul class="small-gap">
|
| +<li>An operand of a command is said to be a <strong>restricted register</strong> iff
|
| +it is a register that is the target of a 32-bit move in the
|
| +immediately-preceding command in the same <em>bundle</em> (consider the
|
| +previous command as additional sandboxing prefix):</li>
|
| +</ul>
|
| +<blockquote>
|
| +<div><pre>
|
| + ; any 32-bit register can be used here; the first operand is
|
| + ; unrestricted but often is the same register)
|
| + mov ..., %eXX
|
| +</pre>
|
| +</div></blockquote>
|
| +<ul class="small-gap">
|
| +<li>Instructions capable of changing <code>%RBP</code> and <code>%RSP</code> are
|
| +forbidden, except the instruction sequences in the whitelist below,
|
| +which must not cross <em>bundle</em> boundaries:</li>
|
| +</ul>
|
| +<blockquote>
|
| +<div><pre>
|
| + mov %rbp, %rsp
|
| + mov %rsp, %rbp
|
| + mov ..., %ebp
|
| + add %rZP, %rbp ; (restoration of %RBP from memory, register or stack - keeps the invariant intact)
|
| + mov ..., %esp
|
| + add %rZP, %rsp ; (restoration of %RSP from memory, register or stack - keeps the invariant intact)
|
| + lea xxx(%rbp), %esp
|
| + add %rZP, %rsp ; (restoration of %RSP from %RBP with adjust)
|
| + sub ..., %esp
|
| + add %rZP, %rsp ; (stack space allocation)
|
| + add ..., %esp
|
| + add %rZP, %rsp ; (stack space deallocation)
|
| + and $XX, %rsp ; (alignment; XX must be between -128 and -1)
|
| + pushq ...
|
| + popq ... ; (except pop %RSP, pop %RBP)
|
| +</pre>
|
| +</div></blockquote>
|
| +</section><section id="list-of-pseudo-instructions">
|
| +<h2 id="list-of-pseudo-instructions">List of Pseudo-instructions</h2>
|
| +<p>Pseudo-instructions were introduced to let the compiler maintain the
|
| +invariants without needing to know the code alignment rules. The
|
| +assembler guarantees 32-bit alignment for all <em>pseudo-instructions</em> in
|
| +the table below. In addition, to the pseudo-instructions, one
|
| +pseudo-operand prefix is introduced: <code>%nacl</code>. Presence of the
|
| +<code>%nacl</code> operand prefix ensures that:</p>
|
| +<ul class="small-gap">
|
| +<li>The instruction <code>"%mov %eXX, %eXX"</code> is added immediately before the
|
| +actual command using prefix <code>%nacl</code> (where <code>%eXX</code> is a 32-bit
|
| +part of the index register of the actual command, for example: in
|
| +operand <code>%nacl:(,%r11)</code>, the notation <code>%eXX</code> is referring to
|
| +<code>%r11d</code>)</li>
|
| +<li>The resulting sequence of two instructions does not cross the
|
| +<em>bundle</em> boundary.</li>
|
| +</ul>
|
| +<p>For example, the instruction:</p>
|
| +<pre>
|
| +mov %eax,%nacl:(%r15,%rdi,2)
|
| +</pre>
|
| +<p>is translated by the assembler to:</p>
|
| +<pre>
|
| +mov %edi,%edi
|
| +mov %eax,(%r15,%rdi,2)
|
| +</pre>
|
| +<p>The complete list of introduced <em>pseudo-instructions</em> is as follows:</p>
|
| +<table border=1>
|
| +<tbody>
|
| +<tr>
|
| +<td>Pseudo-instruction</td>
|
| +<td>Is translated to<br/>
|
| +</td>
|
| +</tr>
|
| +<tr>
|
| +<td>[rep] cmps %nacl:(%rsi),%nacl:(%rdi),%rZP<br/>
|
| +<i>(sandboxed cmps)</i><br/>
|
| +</td>
|
| +<td>mov %esi,%esi<br/>
|
| +lea (%rZP,%rsi,1),%rsi<br/>
|
| +mov %edi,%edi<br/>
|
| +lea (%rZP,%rdi,1),%rdi<br/>
|
| +[rep] cmps (%rsi),(%rdi)<i><br/>
|
| +</i>
|
| +</td>
|
| +</tr>
|
| +<tr>
|
| +<td>[rep] movs %nacl:(%rsi),%nacl:(%rdi),%rZP<br/>
|
| +<i>(sandboxed movs)</i><br/>
|
| +</td>
|
| +<td>mov %esi,%esi<br/>
|
| +lea (%rZP,%rsi,1),%rsi<br/>
|
| +mov %edi,%edi<br/>
|
| +lea (%rZP,%rdi,1),%rdi<br/>
|
| +[rep] movs (%rsi),(%rdi)<i><br/>
|
| +</i>
|
| +</td>
|
| +</tr>
|
| +<tr>
|
| +<td>naclasp ...,%rZP<br/>
|
| +<i>(sandboxed stack increment)</i></td>
|
| +<td>add ...,%esp<br/>
|
| +add %rZP,%rsp</td>
|
| +</tr>
|
| +<tr>
|
| +<td>naclcall %eXX,%rZP<br/>
|
| +<i>(sandboxed indirect call)</i></td>
|
| +<td>and $-32, %eXX<br/>
|
| +add %rZP, %rXX<br/>
|
| +call *%rXX<br/>
|
| +<i>Note: the assembler ensures all calls (including
|
| +naclcall) will end at the bundle boundary.</i></td>
|
| +</tr>
|
| +<tr>
|
| +<td>nacljmp %eXX,%rZP<br/>
|
| +<i>(sandboxed indirect jump)</i></td>
|
| +<td>and $-32,%eXX<br/>
|
| +add %rZP,%rXX<br/>
|
| +jmp *%rXX<br/>
|
| +</td>
|
| +</tr>
|
| +<tr>
|
| +<td>naclrestbp ...,%rZP<br/>
|
| +<i>(sandboxed %ebp/rbp restore)</i></td>
|
| +<td>mov ...,%ebp<br/>
|
| +add %rZP,%rbp</td>
|
| +</tr>
|
| +<tr>
|
| +<td>naclrestsp ...,%rZP
|
| +<i>(sandboxed %esp/rsp restore)</i></td>
|
| +<td>mov ...,%esp<br/>
|
| +add %rZP,%rsp</td>
|
| +</tr>
|
| +<tr>
|
| +<td>naclrestsp_noflags ...,%rZP
|
| +<i>(sandboxed %esp/rsp restore)</i></td>
|
| +<td>mov ...,%esp<br/>
|
| +lea (%rsp,%rZP,1),%rsp</td>
|
| +</tr>
|
| +<tr>
|
| +<td>naclspadj $N,%rZP<br/>
|
| +<i>(sandboxed %esp/rsp restore from %rbp; incudes $N offset)</i></td>
|
| +<td>lea N(%rbp),%esp<br/>
|
| +add %rZP,%rsp</td>
|
| +</tr>
|
| +<tr>
|
| +<td>naclssp ...,%rZP<br/>
|
| +<i>(sandboxed stack decrement)</i></td>
|
| +<td>sub ...,%esp<br/>
|
| +add %rZP,%rsp</td>
|
| +</tr>
|
| +<tr>
|
| +<td>[rep] scas %nacl:(%rdi),%?ax,%rZP<br/>
|
| +<i>(sandboxed stos)</i></td>
|
| +<td>mov %edi,%edi<br/>
|
| +lea (%rZP,%rdi,1),%rdi<br/>
|
| +[rep] scas (%rdi),%?ax<br/>
|
| +</td>
|
| +</tr>
|
| +<tr>
|
| +<td>[rep] stos %?ax,%nacl:(%rdi),%rZP<br/>
|
| +<i>(sandboxed stos)</i></td>
|
| +<td>mov %edi,%edi<br/>
|
| +lea (%rZP,%rdi,1),%rdi<br/>
|
| +[rep] stos %?ax,(%rdi)<br/>
|
| +</td>
|
| +</tr>
|
| +</tbody>
|
| +</table></section></section>
|
| +
|
| +{{/partials.standard_nacl_article}}
|
|
|