OLD | NEW |
(Empty) | |
| 1 {{+bindTo:partials.standard_nacl_article}} |
| 2 |
| 3 <section id="pnacl-undefined-behavior"> |
| 4 <h1 id="pnacl-undefined-behavior">PNaCl Undefined Behavior</h1> |
| 5 <div class="contents local" id="contents" style="display: none"> |
| 6 <ul class="small-gap"> |
| 7 <li><a class="reference internal" href="#overview" id="id1">Overview</a></li> |
| 8 <li><a class="reference internal" href="#specification" id="id2">Specification</
a></li> |
| 9 <li><p class="first"><a class="reference internal" href="#behavior-in-pnacl-bitc
ode" id="id3">Behavior in PNaCl Bitcode</a></p> |
| 10 <ul class="small-gap"> |
| 11 <li><a class="reference internal" href="#well-defined" id="id4">Well-Defined</a>
</li> |
| 12 <li><p class="first"><a class="reference internal" href="#not-well-defined" id="
id5">Not Well-Defined</a></p> |
| 13 <ul class="small-gap"> |
| 14 <li><a class="reference internal" href="#potentially-fixable" id="id6">Potential
ly Fixable</a></li> |
| 15 <li><a class="reference internal" href="#floating-point" id="id7">Floating Point
</a></li> |
| 16 <li><a class="reference internal" href="#hard-to-fix" id="id8">Hard to Fix</a></
li> |
| 17 </ul> |
| 18 </li> |
| 19 </ul> |
| 20 </li> |
| 21 </ul> |
| 22 |
| 23 </div><section id="overview"> |
| 24 <span id="undefined-behavior"></span><h2 id="overview"><span id="undefined-behav
ior"></span>Overview</h2> |
| 25 <p>C and C++ undefined behavior allows efficient mapping of the source |
| 26 language onto hardware, but leads to different behavior on different |
| 27 platforms.</p> |
| 28 <p>PNaCl exposes undefined behavior in the following ways:</p> |
| 29 <ul class="small-gap"> |
| 30 <li><p class="first">The Clang frontend and optimizations that occur on the deve
loper’s |
| 31 machine determine what behavior will occur, and it will be specified |
| 32 deterministically in the <em>pexe</em>. All targets will observe the same |
| 33 behavior. In some cases, recompiling with a newer PNaCl SDK version |
| 34 will either:</p> |
| 35 <ul class="small-gap"> |
| 36 <li>Reliably emit the same behavior in the resulting <em>pexe</em>.</li> |
| 37 <li>Change the behavior that gets specified in the <em>pexe</em>.</li> |
| 38 </ul> |
| 39 </li> |
| 40 <li><p class="first">The behavior specified in the <em>pexe</em> relies on PNaCl
’s bitcode, |
| 41 runtime or CPU architecture vagaries.</p> |
| 42 <ul class="small-gap"> |
| 43 <li>In some cases, the behavior using the same PNaCl translator version |
| 44 on different architectures will produce different behavior.</li> |
| 45 <li>Sometimes runtime parameters determine the behavior, e.g. memory |
| 46 allocation determines which out-of-bounds accesses crash versus |
| 47 returning garbage.</li> |
| 48 <li>In some cases, different versions of the PNaCl translator |
| 49 (i.e. after a Chrome update) will compile the code differently and |
| 50 cause different behavior.</li> |
| 51 <li>In some cases, the same versions of the PNaCl translator, on the |
| 52 same architecture, will generate a different <em>nexe</em> for |
| 53 defense-in-depth purposes, but may cause code that reads invalid |
| 54 stack values or code sections on the heap to observe these |
| 55 randomizations.</li> |
| 56 </ul> |
| 57 </li> |
| 58 </ul> |
| 59 </section><section id="specification"> |
| 60 <h2 id="specification">Specification</h2> |
| 61 <p>PNaCl’s goal is that a single <em>pexe</em> should work reliably in the
same |
| 62 manner on all architectures, irrespective of runtime parameters and |
| 63 through Chrome updates. This goal is unfortunately not attainable, PNaCl |
| 64 therefore specifies as much as it can and outlines areas for |
| 65 improvement.</p> |
| 66 <p>One interesting solution is to offer good support for LLVM’s sanitizer |
| 67 tools (including <a class="reference external" href="http://clang.llvm.org/docs/
UsersManual.html#controlling-code-generation">UBSan</a>) |
| 68 at development time, so that developers can test their code against |
| 69 undefined behavior. Shipping code would then still get good performance, |
| 70 and diverging behavior would be rare.</p> |
| 71 <p>Note that none of these issues are vulnerabilities in PNaCl and Chrome: |
| 72 the NaCl sandboxing still constrains the code through Software Fault |
| 73 Isolation.</p> |
| 74 </section><section id="behavior-in-pnacl-bitcode"> |
| 75 <h2 id="behavior-in-pnacl-bitcode">Behavior in PNaCl Bitcode</h2> |
| 76 <section id="well-defined"> |
| 77 <h3 id="well-defined">Well-Defined</h3> |
| 78 <p>The following are traditionally undefined behavior in C/C++ but are well |
| 79 defined at the <em>pexe</em> level:</p> |
| 80 <ul class="small-gap"> |
| 81 <li>Dynamic initialization order dependencies: the order is deterministic |
| 82 in the <em>pexe</em>.</li> |
| 83 <li>Bool which isn’t <code>0</code>/<code>1</code>: the bitcode instructio
n sequence is |
| 84 deterministic in the <em>pexe</em>.</li> |
| 85 <li>Out-of-range <code>enum</code> value: the backing integer type and bitcode |
| 86 instruction sequence is deterministic in the <em>pexe</em>.</li> |
| 87 <li>Reaching end-of-value-returning-function without returning a value: |
| 88 reduces to <code>ret i32 undef</code> in bitcode.</li> |
| 89 <li>Aggressive optimizations based on type-based alias analysis: TBAA |
| 90 optimizations are done before stable bitcode is generated and their |
| 91 metadata is stripped from the <em>pexe</em>, behavior is therefore |
| 92 deterministic in the <em>pexe</em>.</li> |
| 93 <li>Operator and subexpression evaluation order in the same expression |
| 94 (e.g. function parameter passing, or pre-increment): the order is |
| 95 defined in the <em>pexe</em>.</li> |
| 96 <li>Signed integer overflow: two’s complement integer arithmetic is |
| 97 assumed.</li> |
| 98 <li>Atomic access to a non-atomic memory location (not declared as |
| 99 <code>std::atomic</code>): atomics and <code>volatile</code> variables all lower
to the |
| 100 same compatible intrinsics or external functions, the behavior is |
| 101 therefore deterministic in the <em>pexe</em> (see <a class="reference internal"
href="/native-client/reference/pnacl-c-cpp-language-support.html#memory-model-an
d-atomics"><em>Memory Model and |
| 102 Atomics</em></a>).</li> |
| 103 <li>Integer divide by zero: always raises a fault (through hardware on |
| 104 x86, and through integer divide emulation routine or explicit checks |
| 105 on ARM).</li> |
| 106 </ul> |
| 107 </section><section id="not-well-defined"> |
| 108 <h3 id="not-well-defined">Not Well-Defined</h3> |
| 109 <p>The following are traditionally undefined behavior in C/C++ which also |
| 110 exhibit undefined behavior at the <em>pexe</em> level. Some are easier to fix |
| 111 than others.</p> |
| 112 <section id="potentially-fixable"> |
| 113 <h4 id="potentially-fixable">Potentially Fixable</h4> |
| 114 <ul class="small-gap"> |
| 115 <li><p class="first">Shift by greater-than-or-equal to left-hand-side’s bi
t-width or |
| 116 negative (see <a class="reference external" href="https://code.google.com/p/nati
veclient/issues/detail?id=3604">bug 3604</a>).</p> |
| 117 <ul class="small-gap"> |
| 118 <li>Some of the behavior will be specified in the <em>pexe</em> depending on |
| 119 constant propagation and integer type of variables.</li> |
| 120 <li>There is still some architecture specific behavior.</li> |
| 121 <li>PNaCl could force-mask the right-hand-side to <cite>bitwidth-1</cite>, which |
| 122 could become a no-op on some architectures while ensuring all |
| 123 architectures behave similarly. Regular optimizations could also be |
| 124 applied, removing redundant masks.</li> |
| 125 </ul> |
| 126 </li> |
| 127 <li><p class="first">Using a virtual pointer of the wrong type, or of an unalloc
ated |
| 128 object.</p> |
| 129 <ul class="small-gap"> |
| 130 <li>Will produce wrong results which will depend on what data is treated |
| 131 as a <cite>vftable</cite>.</li> |
| 132 <li>PNaCl could add runtime checks for this, and elide them when types |
| 133 are provably correct (see this CFI <a class="reference external" href="https://c
ode.google.com/p/nativeclient/issues/detail?id=3786">bug 3786</a>).</li> |
| 134 </ul> |
| 135 </li> |
| 136 <li><p class="first">Some unaligned load/store (see <a class="reference external
" href="https://code.google.com/p/nativeclient/issues/detail?id=3445">bug 3445</
a>).</p> |
| 137 <ul class="small-gap"> |
| 138 <li>Could force everything to <cite>align 1</cite>, performance cost should be |
| 139 measured.</li> |
| 140 <li>The frontend could also be more pessimistic when it sees dubious |
| 141 casts.</li> |
| 142 </ul> |
| 143 </li> |
| 144 <li><p class="first">Reaching “unreachable” code.</p> |
| 145 <ul class="small-gap"> |
| 146 <li>LLVM provides an IR instruction called “unreachable” whose effect |
| 147 will be undefined. PNaCl could change this to always trap, as the |
| 148 <code>llvm.trap</code> intrinsic does.</li> |
| 149 </ul> |
| 150 </li> |
| 151 <li>Zero or negative-sized variable-length array (and <code>alloca</code>) aren&
#8217;t |
| 152 defined behavior. PNaCl could insert checks with |
| 153 <code>-fsanitize=vla-bound</code>.</li> |
| 154 </ul> |
| 155 </section><section id="floating-point"> |
| 156 <h4 id="floating-point">Floating Point</h4> |
| 157 <p>PNaCl offers a IEEE-754 implementation which is as correct as the |
| 158 underlying hardware allows, with a few limitations. These are a few |
| 159 sources of undefined behavior which are believed to be fixable:</p> |
| 160 <ul class="small-gap"> |
| 161 <li>Float cast overflow is currently undefined.</li> |
| 162 <li>Float divide by zero is currently undefined.</li> |
| 163 <li>Different rounding modes are currently not usable, which isn’t |
| 164 IEEE-754 compliant. PNaCl could support switching modes (the 4 modes |
| 165 exposed by C99 <code>FLT_ROUNDS</code> macros).</li> |
| 166 <li>The default denormal behavior is currently unspecified, which isn’t |
| 167 IEEE-754 compliant (denormals must be supported in IEEE-754). PNaCl |
| 168 could mandate flush-to-zero, and may give an API to enable denormals |
| 169 in a future release. The latter is problematic for SIMD and |
| 170 vectorization support, where some platforms do not support denormal |
| 171 SIMD operations.</li> |
| 172 <li><code>NaN</code> values are currently not guaranteed to be canonical, see <a
class="reference external" href="https://code.google.com/p/nativeclient/issues/
detail?id=3536">bug |
| 173 3536</a>.</li> |
| 174 <li>It is currently unspecified whether signaling <code>NaN</code> faults.</li> |
| 175 <li>Passing <code>NaN</code> to STL functions (the math is defined, but the |
| 176 function implementation isn’t, e.g. <code>std::min</code> and <code>std::m
ax</code>), is |
| 177 well-defined in the <em>pexe</em>.</li> |
| 178 <li><p class="first">Fast-math optimizations are currently supported before <em>
pexe</em> creation |
| 179 time. A <em>pexe</em> loses all fast-math information when it is |
| 180 created. Fast-math translation could be enabled at a later date, |
| 181 potentially at a perf-function granularity. This wouldn’t affect |
| 182 already-existing <em>pexe</em>, it would be an opt-in feature.</p> |
| 183 <ul class="small-gap"> |
| 184 <li>Fused-multiply-add have higher precision and often execute faster, |
| 185 PNaCl currently disallows them in the <em>pexe</em>. PNaCl could (but |
| 186 currently doesn’t) only generate them in the backend if fast-math |
| 187 was specified and the hardware supports the operation.</li> |
| 188 <li>Transcendentals aren’t exposed by PNaCl’s ABI, they are part of
the |
| 189 math library that is included in the <em>pexe</em>. PNaCl could, but |
| 190 currently doesn’t, use hardware support if fast-math were provided |
| 191 in the <em>pexe</em>.</li> |
| 192 </ul> |
| 193 </li> |
| 194 </ul> |
| 195 </section><section id="hard-to-fix"> |
| 196 <h4 id="hard-to-fix">Hard to Fix</h4> |
| 197 <ul class="small-gap"> |
| 198 <li><p class="first">Null pointer/reference has behavior determined by the NaCl
sandbox:</p> |
| 199 <ul class="small-gap"> |
| 200 <li>Raises a segmentation fault in the bottom <code>64KiB</code> bytes on all |
| 201 platforms, and on some sandboxes there are further non-writable |
| 202 pages after the initial <code>64KiB</code>.</li> |
| 203 <li>Negative offsets aren’t handled consistently on all platforms: |
| 204 x86-64 and ARM will wrap around to the stack (because they mask the |
| 205 address), whereas x86-32 will fault (because of segmentation).</li> |
| 206 </ul> |
| 207 </li> |
| 208 <li><p class="first">Accessing uninitialized/free’d memory (including out-
of-bounds array |
| 209 access):</p> |
| 210 <ul class="small-gap"> |
| 211 <li>Might cause a segmentation fault or not, depending on where memory |
| 212 is allocated and how it gets reclaimed.</li> |
| 213 <li>Added complexity because of the NaCl sandboxing: some of the |
| 214 load/stores might be forced back into sandbox range, or eliminated |
| 215 entirely if they fall out of the sandbox.</li> |
| 216 </ul> |
| 217 </li> |
| 218 <li><p class="first">Executing non-program data (jumping to an address obtained
from a |
| 219 non-function pointer is undefined, can only do <code>void(*)()</code> to |
| 220 <code>intptr_t</code> to <code>void(*)()</code>).</p> |
| 221 <ul class="small-gap"> |
| 222 <li>Just-In-Time code generation is supported by NaCl, but will not be |
| 223 supported by PNaCl’s first release. It will not be possible to mark |
| 224 code as executable in the first release.</li> |
| 225 <li>Offering full JIT capabilities would reduce PNaCl’s ability to |
| 226 change the sandboxing model. It would also require a “jump to JIT |
| 227 code” syscall (to guarantee a calling convention), and means that |
| 228 JITs aren’t portable.</li> |
| 229 <li>PNaCl could offer “portable” JIT capabilities where the code han
ds |
| 230 PNaCl some form of LLVM IR, which PNaCl then JIT-compiles.</li> |
| 231 </ul> |
| 232 </li> |
| 233 <li>Out-of-scope variable usage: will produce unknown data, mostly |
| 234 dependent on stack and memory allocation.</li> |
| 235 <li>Data races: any two operations that conflict (target overlapping |
| 236 memory), at least one of which is a store or atomic read-modify-write, |
| 237 and at least one of which is not atomic: this will be very dependent |
| 238 on processor and execution sequence, see <a class="reference internal" href="/na
tive-client/reference/pnacl-c-cpp-language-support.html#memory-model-and-atomics
"><em>Memory Model and |
| 239 Atomics</em></a>.</li> |
| 240 </ul> |
| 241 </section></section></section></section> |
| 242 |
| 243 {{/partials.standard_nacl_article}} |
OLD | NEW |