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