@@ -39,16 +39,16 @@ runtime, WebAssembly programs are protected from control flow hijacking attacks.
39
39
* [ Indirect function calls] ( Rationale.md#indirect-calls ) are subject to a type
40
40
signature check at runtime; the type signature of the selected indirect
41
41
function must match the type signature specified at the call site.
42
- * A shadow stack is used to maintain a trusted call stack that is invulnerable
43
- to buffer overflows in the module heap, ensuring safe function returns.
42
+ * A protected call stack that is invulnerable to buffer overflows in the
43
+ module heap ensures safe function returns.
44
44
* [ Branches] ( Semantics.md#branches-and-nesting ) must point to valid
45
45
destinations within the enclosing function.
46
46
47
47
Variables in C/C++ can be lowered to two different primitives in WebAssembly,
48
48
depending on their scope. [ Local variables] ( Semantics.md#local-variables )
49
49
with fixed scope and [ global variables] ( Semantics.md#global-variables ) are
50
50
represented as fixed-type values stored by index. The former are initialized
51
- to zero by default and are stored in the protected shadow stack, whereas
51
+ to zero by default and are stored in the protected call stack, whereas
52
52
the latter are located in the [ global index space] ( Modules.md#global-index-space )
53
53
and can be imported from external modules. Local variables with
54
54
[ unclear static scope] ( Rationale.md#locals ) (e.g. are used by the address-of
@@ -83,7 +83,7 @@ affect local or global variables stored in index space, they are fixed-size and
83
83
addressed by index. Data stored in linear memory can overwrite adjacent objects,
84
84
since bounds checking is performed at linear memory region granularity and is
85
85
not context-sensitive. However, the presence of control-flow integrity and
86
- protected shadow call stacks prevents direct code injection attacks. Thus,
86
+ protected call stacks prevents direct code injection attacks. Thus,
87
87
common mitigations such as [ data execution prevention] [ ] (DEP) and
88
88
[ stack smashing protection] [ ] (SSP) are not needed by WebAssembly programs.
89
89
@@ -112,13 +112,68 @@ in-order execution and [post-MVP atomic memory primitives
112
112
Similarly, [ side channel attacks] [ ] can occur, such as timing attacks against
113
113
modules. In the future, additional protections may be provided by runtimes or
114
114
the toolchain, such as code diversification or memory randomization (similar to
115
- [ address space layout randomization] [ ] (ASLR)), [ bounded pointers] [ ] ("fat"
116
- pointers), or finer-grained control-flow integrity.
115
+ [ address space layout randomization] [ ] (ASLR)), or [ bounded pointers] [ ] ("fat"
116
+ pointers).
117
+
118
+ ### Control-Flow Integrity
119
+ The effectiveness of control-flow integrity can be measured based on its
120
+ completeness. Generally, there are three types of external control-flow
121
+ transitions that need to be protected, because the callee may not be trusted:
122
+ 1 . Direct function calls,
123
+ 2 . Indirect function calls,
124
+ 3 . Returns.
125
+
126
+ Together, (1) and (2) are commonly referred to as "forward-edge", since they
127
+ correspond to forward edges in a directed control-flow graph. Likewise (3) is
128
+ commonly referred to as "back-edge", since it corresponds to back edges in a
129
+ directed control-flow graph. More specialized function calls, such as tail
130
+ calls, can be viewed as a combination of (1) and (3).
131
+
132
+ Typically, this is implemented using runtime instrumentation. During
133
+ compilation, the compiler generates an expected control flow graph of program
134
+ execution, and inserts runtime instrumentation at each call site to verify that
135
+ the transition is safe. Sets of expected call targets are constructed from the
136
+ set of all possible call targets in the program, unique identifiers are assigned
137
+ to each set, and the instrumentation checks whether the current call target is
138
+ a member of the expected call target set. If this check succeeds, then the
139
+ original call is allowed to proceed, otherwise a failure handler is executed,
140
+ which typically terminates the program.
141
+
142
+ In WebAssembly, the execution semantics implicitly guarantee the safety of (1)
143
+ through usage of explicit function section indexes, and (3) through a protected
144
+ call stack. Additionally, the type signature of indirect function calls is
145
+ already checked at runtime, effectively implementing coarse-grained type-based
146
+ control-flow integrity for (2). All of this is achieved without explicit runtime
147
+ instrumentation in the module. However, as discussed
148
+ [ previously] ( #memory-safety ) , this protection does not prevent code reuse
149
+ attacks with function-level granularity against indirect calls.
150
+
151
+ #### Clang/LLVM CFI
152
+ The Clang/LLVM compiler infrastructure includes a [ built-in implementation] of
153
+ fine-grained control flow integrity, which has been extended to support the
154
+ WebAssembly target. It is available in Clang/LLVM 3.9+ with the
155
+ [ new WebAssembly backend] .
156
+
157
+ Enabling fine-grained control-flow integrity (by passing ` -fsanitize=cfi ` to
158
+ emscripten) has a number of advantages over the default WebAssembly
159
+ configuration. Not only does this better defend against code reuse attacks that
160
+ leverage indirect function calls (2), but it also enhances the built-in function
161
+ signature checks by operating at the C/C++ type level, which is semantically
162
+ richer that the WebAssembly [ type level] ( AstSemantics.md#types ) , which consists
163
+ of only four value types. Currently, enabling this feature has a small
164
+ performance cost for each indirect call, because an integer range check is
165
+ used to verify that the target index is trusted, but this will be eliminated in
166
+ the future by leveraging built-in support for
167
+ [ multiple indirect tables] ( Modules.md#table-index-space ) with homogeneous type
168
+ in WebAssembly.
117
169
118
170
[ address space layout randomization ] : https://en.wikipedia.org/wiki/Address_space_layout_randomization
119
171
[ bounded pointers ] : https://en.wikipedia.org/wiki/Bounded_pointer
172
+ [ built-in implementation ] : http://clang.llvm.org/docs/ControlFlowIntegrity.html
120
173
[ control-flow integrity ] : https://research.microsoft.com/apps/pubs/default.aspx?id=64250
121
174
[ data execution prevention ] : https://en.wikipedia.org/wiki/Executable_space_protection
175
+ [ forward-edge control-flow integrity ] : https://www.usenix.org/node/184460
176
+ [ new WebAssembly backend ] : https://github.com/WebAssembly/binaryen#cc-source--webassembly-llvm-backend--s2wasm--webassembly
122
177
[ return-oriented programming ] : https://en.wikipedia.org/wiki/Return-oriented_programming
123
178
[ same-origin policy ] : https://www.w3.org/Security/wiki/Same_Origin_Policy
124
179
[ side channel attacks ] : https://en.wikipedia.org/wiki/Side-channel_attack
0 commit comments