• No results found

6.4 Implementation

6.5.3 Microbenchmarks and Optimizations

ScriptPolice incorporates two mechanisms for policy enforcement: the interposition interface and IFC. Below, we evaluate the distinct costs of these mechanisms. We first consider IFC, as used by the Preven- tion policy to track the propagation of data derived from pages within extensions.

We benchmark the performance of various arithmetic, string, and JSObject operations on tainted data vs. the performance of these operations on non-tainted data. Table 6.5 shows these measurements in operations per microsecond. The benchmark results presented in Table 6.5 are geometric means of ten runs, and the standard deviations among the runs are below 5%.

First, consider the performance of our initial IFC-enabled V8 implementation that did not JIT op- erations on tainted data (Section 6.4.3) but interpreted them in the V8 runtime, as shown in the No JIT column in Table 6.5. Interpreting operations is extremely slow, incurring 37x overhead on average, as for every operation execution must enter the V8 runtime. Crossing the boundary between native, JITed code and the V8 runtime for each operation results in a drastic degradation of performance. Emitting JIT’ed native code for operations on tainted data significantly improves performance; the average slowdown drops from 37x to 1.25x, as shown in the No JIT vs. JIT columns.

The JIT column in Table 6.5 shows the costs of operations on tainted data relative to those of same operations on non-tainted data, shown in the Vanilla column. To propagate taint, ScriptPolice must emit additional label propagation code before and after each operation that processes tainted data. The additional code untaints arguments, thus allowing an operation to proceed with non-tainted data, and

Operation Spec No Taint No Spec No Taint Add-Int 102.99 99.84 (1.03x) Sub-Int 103.85 99.92 (1.04x) Mul-Int 101.35 95.00 (1.07x) Div-Int 78.86 77.63 (1.02x) Add-Float 89.04 76.29 (1.17x) Sub-Float 88.87 76.18 (1.17x) Mul-Float 89.02 76.25 (1.17x) Div-Float 86.37 75.57 (1.14x) Add-Str 59.06 56.57 (1.04x) Load-Int 111.80 106.77 (1.05x) Load-Obj 112.41 107.14 (1.05x) Store-Int 94.20 99.26 (0.95x) Store-Obj 97.41 96.83 (1.01x) Numbers are operations/µs with relative slowdowns in parentheses. No Taint – op- erations on non-tainted data, Spec/No Spec – the specialized taint tracking optimization is enabled/disabled. Load/Store loads/stores a type specified in the operation’s name from/to a JSObject.

Table 6.6: Evaluation of the Specialized Taint Tracking Optimization.

Operation Vanilla Interpret Policy Check Policy Invoke Call 46.57 19.87 (2.34x) 2.93 (15.87x) 2.12 (21.93x) Load 47.69 9.74 (4.89x) 2.80 (17.03x) 1.94 (24.59x) Store 26.40 8.43 (3.13x) 2.37 (11.14x) 1.84 (14.37x) Numbers are operations/µs with relative slowdowns in parentheses. Interpret shows the cost of interpreting operations without policy checks or monitor- ing function invocations; Policy Check adds the cost of performing a policy check, but no monitoring function invocations; Policy Invoke is the additional cost of invoking a monitoring function that does no work.

Table 6.7: Execution Overhead of Operations on Sources and Sinks.

then taints the operation’s result if the arguments were tainted. The taint propagation code incurs 1.25x average slowdown.

We now consider the performance benefit afforded by specialization for non-tainted data types, as described in Section 6.4.3, which allows the omission of label propagation instructions for operations that compute on non-tainted data. Table 6.6 shows the performance improvement achieved by this specialized taint tracking optimization. We present the performance of operations on non-tainted data when the optimization is enabled in the Spec column, and when it is not in the No Spec column. In the former case, V8 emits no label propagation code, and in the latter case, it emits such code even though the operations do not process tainted data. The specialized taint tracking optimization reduces execution time by 7% on average.

Our optimizations reduce the overhead of label propagation to tractable levels. However, Script- Police policies also invoke an interposition interface on data sources, code sources, and data sinks. The current implementation of interposition in ScriptPolice is in fact the major source of execution overhead in policy enforcement, as shown below.

ScriptPolice vs. in “vanilla” V8. (Note that V8 implements sources and sinks in the same way.) We further categorize the total cost of operations on sources and sinks into three components. First, we show the overhead caused by interpreting operations on sources and sinks in the Interpret column. Our current implementation does not support JITing for such operations. Then, we measure the cost of a policy check, which examines if a policy function is attached to a source or sink, as shown in the Policy Checkcolumn. Note that the interpretation cost is included in the policy check cost. Finally, we look at the cost of a policy function call, shown in the Policy Invoke column, where each operation on the source results in an invocation of a policy function that does no work but returns immediately. The Policy Invoke overhead is the total overhead of operations on sources and sinks, and it includes all three of the prior components.

Interpreting operations on sources and sinks results in an average 3.5x slowdown. A policy check increases the average slowdown up to 15x, and a monitoring function invocation further raises the over- head to 20x. In a real-world scenario, we expect the slowdowns introduced by monitoring functions to be greater than the one presented in our benchmark evaluation because a single source or sink may have multiple monitoring functions performing actual work.