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