[PATCH] D21768: Support CFI for WebAssembly target

Dominic Chen via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 11 15:34:24 PDT 2016


ddcc added a comment.

Yes, in WebAssembly, most uses of memory addresses (pointers) are replaced with indexes into the appropriate section. As part of this, all functions and their types must be explicitly declared, and functions which can be called indirectly must be explicitly listed in a "table" section. The only remaining use of memory addresses is to an isolated linear memory region (for emulating a stack, etc), but this can only be used for storing data. Replacing function pointers with indexes is handled in s2wasm (compile/run process: c/c++ -> emscripten (clang -> opt -> llc -> s2wasm) -> browser) , which looks for functions that have their address taken, generates a table entry for each, and uses the table entry index as the "address". Additionally, s2wasm includes the expected type of the indirect function with the indirect function call. At runtime, two checks are performed at each indirect function call: (1) the specified index is a valid entry in the "table" section, and (2) the type signature specified at the call site matches the call site of the selected function (NULL "function pointers" would presumably fail this). If either of these is violated, then a runtime trap is generated.

However, this current approach has some downsides: it doesn't protect against code reuse attacks, and the signature check is fairly coarse grained, since it is performed at the WebAssembly type level (which only has four unique types: int/float, 32/64-bit). This patch adds support for Clang/LLVM's CFI implementation in WebAssembly programs, by pre-assigning continuous indexes in LLVM for each disjoint set, and introducing a new primitive (.indidx) to tell the linker that a function must be given an index. The corresponding patch to the linker first preallocates indexes for functions with a preassigned index, then falls back to the normal behavior of generating new entries for each remaining function called indirectly. Unfortunately, this approach corrects the two drawbacks, but adds some runtime overhead. A future patch will use support for multiple tables with homogeneous type in WebAssembly to eliminate the runtime CFI overhead.

Dynamic linking support (https://github.com/WebAssembly/design/blob/master/DynamicLinking.md) has only recently been introduced into WebAssembly as of approx. two weeks ago, and the interaction between CFI and dynamic linking hasn't been decided yet. Currently, calling `dlsym` finds the imported function, copies it to the function and table sections of the host, and returns its index for use in an indirect call. Clearly, this doesn't work well with CFI; different implementations include requiring a forward declaration of dynamically-linked functions for placeholder entries, fixing table offsets and set boundaries at runtime, etc. Alternatively, if tables with homogeneous type are used for CFI, then the tables from two modules could just be joined directly: two tables with the same type are merged, otherwise new tables are created and table references are updated.


http://reviews.llvm.org/D21768





More information about the llvm-commits mailing list