Case Studies

Testbed: two identical machines, one as client and one as server. The characteristics of machines and the network can be found in the Methodology page.

Apache web server

  • Version: 2.4.18
  • Configuration: default (MPM event model: hybrid multi-process multi-threaded)
  • Dependencies1:
    • OpenSSL 1.0.1f (susceptible to the Heartbleed bug)
    • apr-1.5.2
    • apr-util-1.5.4
    • PCRE 8.38
  • Workload:
    • ab benchmark
    • with keepalive connections
    • fetching of a 2.3K static web-page
    • using HTTP get

Performance

Apache throughput-latency plot

Additional statistics2:

 NativeMPXASan
Network utilization (MBit/s)865850865
CPU utilization (%)480510500
Instructions/cycle0.60.630.74
Resident Set Size (MB)9.412033
Minor page faults (K)2.64.19.6
L1 cache misses (%)121412
LLC cache misses (%)1.281.6
(network is a bottleneck in all cases)   

Performance Summary: GCC-MPX, ICC-MPX, and AddressSanitizer all show minimal overheads, achieving 95.3%, 95.7%, and 97.5% of native throughput. Overhead in latency did not exceed 5%. Such good performance is explained by the fact that our experiment was limited by the network and not CPU or memory.

Memory Summary: AddressSanitizer exhibits an expected 3.5X overhead. In contrast, MPX variants have dramatic 12.8X increase in memory consumption. This is explained by the fact that Apache allocates an additional 1MB of pointer-heavy data per each client, which in turn leads to the allocation of many Bounds Tables.

Security

Results:

 NativeMPXASan
Bug detectednoyesyes

Summary: AddressSanitizer and GCC-MPX detect Heartbleed without any problems.

Note. The actual situation with Heartbleed is more contrived. OpenSSL uses its own memory manager which partially bypasses the wrappers around malloc and mmap. Thus, in reality memory-safety approaches find Heartbleed only if the length parameter is greater than 32KB (the granularity at which OpenSSL allocates chunks of memory for its internal allocator). More info.

Usability

Issue 1: While testing against Heartbleed, we discovered that ICC-MPX suffers from a run-time Intel compiler bug 5 in the x509_cb OpenSSL function, leading to a crash of Apache. This bug triggered only on HTTPS connections, thus allowing us to still run performance experiments on ICC-MPX. See bug here.

Up to table of contents


Nginx web server

  • Version: 1.4.0 (susceptible to this bug)
  • Configuration: worker_processes = auto (1 process per core)
  • Dependencies1: OpenSSL 1.0.1f
  • Workload:
    • ab benchmark
    • with keepalive connections
    • fetching of a 2.3K static web-page
    • using HTTP get

Performance

Nginx throughput-latency plot

Additional statistics2:

 NativeMPXASan
Network utilization (MBit/s)850840840
CPU utilization (%)225265300
Instructions/cycle0.810.820.81
Resident Set Size (MB)4.318380
Minor page faults (K)2.04.51250
L1 cache misses (%)91010
LLC cache misses (%)0.70.79
(network is a bottleneck in all cases)   

Performance Summary: AddressSanitizer reaches 95% of native throughput, while GCC-MPX and ICC-MPX lag behind with 86% and 89.5% respectively. Similar to Apache, this experiment was network-bound, with CPU usage of 225% for native, 265% for MPX, and 300% for AddressSanitizer. (CPU usage numbers prove that HW-assisted approaches impose less CPU overheads.)

Memory Summary: MPX variants have a reasonable 4.2X memory overhead, but AddressSanitizer eats up 88X more memory (it also has 625X more page faults and 13% more LLC cache misses).

Why MPX is slower than AddressSanitizer if their memory characteristics indicate otherwise? The reason for the horrifying AddressSanitizer numbers is its quarantine feature – AddressSanitizer employs a special memory management system which avoids re-allocating the same memory region for new objects, thus decreasing the probability of temporal bugs such as use-after-free. Due to quarantine, AddressSanitizer experiences huge memory blow-up. When we disabled this feature, AddressSanitizer used only 24MB of memory.

Security

Note. To exploit the bug, one needs to apt-get install gem rubygems ruby-dev sqlite3 libsqlite3-dev and gem install ronin in Ubuntu.

Results:

 NativeMPXASan
Bug detectednonoyes

Summary: AddressSanitizer detects this bug, but both versions of MPX do not. The root cause is the run-time wrapper library: AddressSanitizer wraps all C library functions including recv, and the wrapper – not the Nginx instrumented code – detects the stack buffer overflow. In case of both GCC-MPX and ICC-MPX, only the most widely used functions are wrapped and bounds-checked. That is why when recv is called, the overflow happens in the unprotected C library function and goes undetected by MPX.

Usability

Issue 1: To successfully run Nginx under GCC-MPX with narrowing of bounds, we had to manually fix a variable-length array name[1] in the ngx_hash_elt_t struct to name[0].

Issue 2: ICC-MPX first crashed with a false positive in ngx_http_merge_locations function. The reason for this bug was a cast from a smaller type, which rendered the bounds too narrow for the new, larger type. Note that GCC-MPX did not experience the same problem because it enforces the first struct’s field to inherit the bounds of the whole object by default – in contrast to ICC-MPX which takes a more rigorous stance. For our evaluation, we used the version of ICC-MPX with narrowing of bounds disabled.

Up to table of contents


Memcached caching system

  • Version: 1.4.15 (susceptible to this bug)
  • Configuration: 8 threads (to keep all CPU cores busy)
  • Dependencies1: libevent 2.0.22-stable
  • Workload:
    • memaslap benchmark from libmemcached 1.0.16
    • with 10% ~400B sets and 90% ~1,700B gets

Performance

Memcached throughput-latency plot

Additional statistics2:

 NativeMPXASan
Network utilization (MBit/s)850595850
CPU utilization (%)300320345
Instructions/cycle0.850.70.92
Resident Set Size (MB)7335295
Minor page faults (K)188626
L1 cache misses (%)111311
LLC cache misses (%)6136
(network is a bottleneck only for native and ASan)   

Performance Summary: AddressSanitizer performs on par with the native version. Both GCC-MPX and ICC-MPX achieved only 48−50% of maximum native throughput. In case of native and AddressSanitizer, performance of Memcached was limited by network. But it was not the case for MPX: Memcached exercised only 70% of the network bandwidth.

Memory Summary: While AddressSanitizer imposed only 30% memory overhead, both MPX variants used 350MB of memory (4.8X more than native). This huge memory overhead broke cache locality and resulted in 5.4X more page faults and 10−15% LLC misses, making MPX versions essentially memory-bound. (Indeed, the CPU utilization never exceeded 320%.)

Security

Results:

 NativeMPXASan
Bug detectednoyesyes

Summary: All approaches detected buffer overflow in the affected function’s arguments and stopped the execution.

Usability

We experienced no usability problems.

Up to table of contents

  1. All dependencies (libraries) are built from source code and statically linked.  2 3

  2. All statistics are shown for the maximum achievable throughput and only for GCC versions; MPX showed similar results on GCC and ICC.  2 3