worse, one possible factor is code size, as mentioned
above. Increases in NaCl code size due to alignment can
be as much as 50%, especially in programs like the gcc
SPEC2000 benchmark with a large number of static call
sites. Similarly, benchmarks with a large amount of control flow branching (e.g., crafty, vortex) have a higher code
size growth due to branch target alignment. The incremental code size increase of sandboxing with nacljmp is
consistently small.
Overall, the performance impact of Native Client on
these benchmarks is on average less than 5%. At this
level, overhead compares favorably to untrusted native
execution.
4. 2. H.264 decoder
We ported an internal implementation of H.264 video
decoding to evaluate the difficulty of the porting effort.
The original application converted H.264 video into a raw
file format, implemented in about 11K lines of C for the
standard GCC environment on Linux. We modified it to
play video. The port required about 20 lines of additional C
code, more than half of which was for error checking. Apart
from rewriting the Makefile, no other modifications were
required. This experience is consistent with our general
experience with Native Client; legacy Linux libraries that
do not inherently require network and file access generally port with minimal effort. Performance of the original
and NaCl versions were comparable and limited by video
frame-rate.
4. 3. Quake
We profiled sdlquake- 1.0.9f using the built-in “timedemo
demo1” command. Quake was run at 640 × 480 resolution
on a Ubuntu Dapper Drake Linux box with a 2. 4 GHz Intel
Q6600 quad core CPU. The video system’s vertical sync
(VSYNC) was disabled. The Linux executable was built
using gcc version 4.0.3, and the Native Client version with
nacl-gcc version 4. 2. 2, both with -02 optimization.
With Quake, the differences between Native Client
and the normal executable are, for practical purposes,
indistinguishable. See Table 2 for the comparison. We
observed very little nondeterminism between runs. The
test plays the same sequence of events regardless of
frame rate. Slight variances in frame rate can still occur
due to the OS thread scheduler and pressure applied to
the shared caches from other processes. Although Quake
uses software rendering, the performance of the final bitmap transfer to the user’s desktop may depend on how
busy the video device is.
5. Discussion
As described above, Native Client has inner and outer
sandboxes, redundant barriers to protect native operating system interfaces. Additional measures such as a CPU
blacklist and NaCl module blacklist will also be deployed.
We have developed and tested Native Client on Ubuntu
Linux, MacOS, and Microsoft Windows XP. Overall we are
satisfied with the interaction of Native Client with these
operating systems. That being said, there are areas where
better operating system support would help. As an example,
popular operating systems require all threads to use a flat
addressing model in order to deliver exceptions correctly.
Use of segmented memory prevents these systems from
interpreting the stack pointer and other essential thread
state. Through better operating system segment support
we could resolve this problem and provide hardware exception support in untrusted code. However, note that due to
our portability requirement we could not enable exception
support for untrusted modules unless all native OSes support it. This least-common-denominator effect also arises
in other parts of the system, such as the 256MB address
space limit for NaCl modules.
With respect to programming languages and language
implementations, we are encouraged by our initial experience with Native Client and the GNU tool chain, and are
looking at porting other compilers. We have also ported
two interpreters, Lua and awk. While it would be challenging to support JITted languages such as Java, we are hopeful that Native Client might someday allow developers to
use their language of choice in the browser rather than
being restricted to JavaScript.
6. RelATeD WoRk
Techniques for safely executing third-party code generally
fall into four categories: system request moderation, virtu-alization, fault isolation, and trust with authentication.
Kernel-based mechanisms such as user-id-based access
controls, systrace20 and ptrace25 are familiar facilities on
Unix-like systems. Many projects have applied such mechanisms to containing untrusted code, most recently Android2
from Google and Xax9 from Microsoft Research. While they
can be very effective, these approaches require dependencies on the native operating system. These dependencies
in turn can interfere with portability, and expose more of
the native operating system in the attack surface. Our inner
sandbox design was heavily influenced by goals of portability and operating system independence.
Many research and practical systems apply abstract
virtual machines to constrain untrusted code. While they
commonly support ISA portability, they also tend to create
a performance obstacle that we avoid by working directly
with machine code. A further advantage of expressing
sandboxing directly in machine code is that it does not rely
on a trusted compiler or interpreter. This greatly reduces
the size of the trusted computing base,
26 and has a further
Table 2. Quake performance comparison. numbers are in frames
per second.
Run
1
2
3
Average
native client
143.2
143.6
144.2
143.7
linux executable
142.9
143.4
143.5