Google Native Client Puts x86 On the Web 367
t3rmin4t0r writes "Google has announced its Google native client, which enables x86 native code to be run securely inside a browser. With Java applets already dead and buried, this could mean the end of the new war between browsers and the various JavaScript engines (V8, Squirrelfish, Tracemonkey). The only question remains whether it can be secured (ala ActiveX) and whether the advantages carry over onto non-x86 platforms. The package is available for download from its Google code site. Hopefully, I can finally write my web apps in asm." Note: the Google code page description points out that this is not ready for production use: "We've released this project at an early, research stage to get feedback from the security and broader open-source communities." Reader eldavojohn links to a technical paper linked from that Google code page [PDF] titled "Native Client: A Sandbox for Portable, Untrusted x86 Native Code," and suggests this in-browser Quake demo, which requires the Native Code plug-in.
Re:doesn't sound too secure yet (Score:2, Informative)
by definition x86 code is not portable across platforms
Sure it is, you just write a JIT compiler from x86 to your native machine code, thus COMPLETELY nulling any advantage this has over other JIT languages :)
Re:doesn't sound too secure yet (Score:5, Informative)
Re:doesn't sound too secure yet (Score:3, Informative)
One might say the same thing about p-code (;-))
--dave
Re:doesn't sound too secure yet (Score:2, Informative)
Or you could write an application that downloads the photo into the browser and manipulates it in a Canvas [mozilla.org]. It's not like these APIs are any huge secret. You'd think that someone working for Google would know about that [sourceforge.net]. I won't even get into using the ubiquitous Flash 9 plugin to accomplish the same goal.
As you said, their example is AWFUL.
Re:doesn't sound too secure yet (Score:5, Informative)
x86 code runs natively on 90% of the processors out there. Java or .NET bytecode runs natively on about 0% of them (Sun did have a Java chip once but it is long dead). So it is hardly any worse than the alternatives. There are many x86 emulators and some of them have reasonable performance.
ARM Jazelle (in quite a number of the ARM revisions deployed all over the place) includes DBX for direct bytecode execution of Java. That includes the iphone and loads of other stuff.
Re:doesn't sound too secure yet (Score:4, Informative)
From the article linked from the story, emphasis mine:
The release contains the experimental compilation tools and runtime so that you can write and run portable code modules that will work in Firefox, Safari, Opera, and Google Chrome on any modern Windows, Mac, or Linux system that has an x86 processor. We're working on supporting other CPU architectures (such as ARM and PPC) to make this technology work on the many types of devices that connect to the web today.
Reading Comprehension FTW!
Re:Two steps backward (Score:3, Informative)
Try Java6 update 10 and you'll be surprised. The plugin loads instantaneously and I believe applets load jars on demand as well.
This is rather clever (Score:5, Informative)
This is a fascinating effort. Read the research paper. [googlecode.com]
This is really a little operating system, with 44 system calls. Those system calls are the same on Linux, MacOS (IA-32 version) and Windows. That could make this very useful - the same executable can run on all major platforms.
Note that you can't use existing executables. Code has to be recompiled for this environment. Among other things, the "ret" instruction has to be replaced with a different, safer sequence. Also, there's no access to the GPU, so games in the browser will be very limited. As a demo, they ported Quake, but the rendering is entirely on the main CPU. If they wanted to support graphics cross-platform, they could put in OpenGL support.
Executable code is pre-scanned by the loader, sort of like VMware. Unlike VMware, the hard cases are simply disallowed, rather than being interpreted. Most of the things that are disallowed you wouldn't want to do anyway except in an exploit.
This sandbox system makes heavy use of some protection machinery in IA-32 that's unused by existing operating systems. IA-32 has some elaborate segmentation hardware which allows constraining access at a fine-grained level. I once looked into using that hardware for an interprocess communication system with mutual mistrust, trying to figure out a way to lower the cost of secure IPC. There's a seldom-used "call gate" in IA-32 mechanism that almost, but not quite, does the right thing in doing segment switches at a call across a protection boundary. The Google people got cross-boundary calls to work with a "trampoline code" system that works more like a system call, transferring from untrusted to trusted code. This is more like classic "rings of protection" from Multics.
Note that this won't work for 64-bit code. When AMD came up with their extension to IA-32 to 64 bits, they decided to leave out all the classic x86 segmentation machinery because nobody was using it. (I got that info from the architecture designer when he spoke at Stanford.) 64-bit mode is flat address space only.
Re:Two steps backward (Score:3, Informative)
You seem to be confusing the instruction set with the underlying implementation. Core 2 is awesome. The instruction set is not. So much so that it must be translated into a decent set of instructions by microcode before the processor can pass it through the decoder and ALU.
Oh, I don't know. Instructions for 64-bit programming piled upon instructions for 32-bit programming piled upon instructions for 16-bit programming piled upon instructions for 8-bit programming, all with a half-dozen memory modes to choose from, four different register access methods, special use of particular registers in certain modes, complex instructions added willy-nilly only to be deprecated into slow microcode later on, four different SIMD schemes, a few different floating point modes, a variety of segmentation schemes (none of which are used), support for context switching (that no one uses), variable length instructions, etc, etc, etc.
x86 is about the worst instruction set known to man. (Which is kind of amusing when you consider that it became the most used instruction set ever.) Even if we assume that the system will only allow a small subset of x86 code, there is still the very real possibility that it will be impossible to protect against the full ISA when executing code natively. Just off the top of my head, I'm already thinking of carefully crafting instructions so that they seem correct when the verifier passes over them in sequence, but actually execute as different instructions when the jump is executed into what appears to be the middle of an instruction. Oops.
Yeah, I have. I could kill my cat by accidentally dropping heavy reference manuals sitting on my shelf. The x86 instruction set is far too large, overly complex, redundant, antiquated, and poorly suited as a replacement for VM-targeted instruction sets like Java bytecode.
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." --Donald Knuth
"Speed" is a terrible excuse for attempting a platform like this. Especially when APIs can cover the 3% performance gap that Knuth referred to. I don't need to write a GL renderer in Javascript. I can simply call the necessary APIs [opera.com] to manipulate the native GL instance for me. That's more than fast enough for compute-intensive graphics.
Re:doesn't sound too secure yet (Score:5, Informative)
An interpreter compiles each instruction every time it gets executed.
JIT compiles blocks of code only on first execution. Next time, the compiled code is already in memory.
Re:doesn't sound too secure yet (Score:3, Informative)
Have you tried Java 6 Update 10?
Re:doesn't sound too secure yet (Score:4, Informative)
Why not? It just means that the permissible instruction sequences are limited to a subset that can be statically analyzed and verified to be safe. The Java VM has similar verification algorithms that are run whenever untrusted code is first loaded.
It's true that this does not allow all x86 code to run; it's at least practically (and probably theoretically) impossible to correctly determine whether or not a piece of code is safe, but as long as the VM errs on the side of caution, there shouldn't be any problems with this approach.
I will grant that this makes it unclear what the advantage is over (say) Java applets. What can this technology do that the Java VM couldn't? As far as I'm concerned, the failure of Java in the browser has more to do with the lack of a standard library for high-performance multimedia applications (think: Flash) than with shortcomings in the bytecode language.
All this means is that google have created a VM in which the "bytecodes" happen to be executable on real hardware, but some of these "bytecodes" have to be intercepted and replaced at runtime with substitute code... this aught to sound familiar; this is what a software hypervisor does (eg VMware).
In other words every man and his dog has jumped aboard the "I can write an x86-hypervisor" bandwagon, the difference being that google have decided to take theirs and embed it into the browser rather than run as a standalone app.
Interestingly enough it took the momentum that VMware created to get intel to correct some of the issues with its' ISA to make it much easier to virtualise [wikipedia.org], perhaps someone the size of google can prod intel into adding a third wave of virtualisation accelartion extensions to their ISA so as to make this idea safer* with low overhead
*I think virtualisation is a useful thing (I make a living from consulting on it), however I am unconvinced [wikipedia.org] of it being possible, to truly [wikipedia.org] secure [kerneltrap.org] it.
Re:This is rather clever (Score:3, Informative)
Re:doesn't sound too secure yet (Score:3, Informative)
When you're managing native code, it only takes one slip-up to hand over the keys to the kingdom. That slip-up may be as simple as a two byte exploit, but it's a slip-up none the less. One must be VERY careful with native code because there is no way to prove that it is safe to execute natively.
Hypervisor features in modern processors simplify the issue somewhat, but it is still not proven that hypervisors are without exploits.
That's not at all true, though, and you certainly don't need any supervisor CPU features. It is quite easy to run native code completely securely -- all you need to do is set up a private virtual memory space for the managed code, and only provide it with a call gate to your own program code through which it can do controlled requests. It's done at large scale -- it's called a "process" in normal OS parlance. You may have heard of the term
The normal problem is just that the operating system gives too much privilege to all processes, such that any running process can access the filesystem, the network stack, can allocate limitless amounts of memory (swappable memory, but nevertheless) and so on. However, that's a problem with the operating system, not with the CPU. In fact, later versions of Linux has a special process mode called SECCOMP [wikipedia.org], in which the process may only call exit(), read() and write() (the latter two only on already open file descriptors), which could certainly be used to implement Google's idea completely securely.
The problem in this case, that the OP complained about was that Google seems to only blacklist certain program data bytes, which is most likely unsafe, as there are probably other code paths left that could be used to execute unsafe code that noone would have thought to blacklist.
My point is just that there's no reason to think that a JVM is inherently more secure than an x86 CPU. It's just the Java class library that's more secure than your standard off-the-shelf operating system.
Re:Two steps backward (Score:3, Informative)
I'll put this as simply as I can. Javascript execution is like this:
1. Read <script src="a.js">
2. Execute a.js
3. Read <script src="b.js">
4. Execute b.js
5. Read <script src="c.js">
6. Execute c.js
See how that happens as part of the page load? Now let's look at a similar Java app:
1. Read <applet src="app.jar" code="a">
2. Create a new thread and turn over execution to the JVM
3. Download app.jar
4. Read Manifest.mf to load references to any necessary libraries
5. Extract a.class
6. Verify a.class
7. Extract b.class
8. Verify b.class
9. Extract c.class
10. Verify c.class
11. Initialize a.class
12. Initialize b.class
13. Initialize c.class
14. Execute a.class
Somewhere in there the JVM downloads library JARs referenced by app.jar. When this happens and how is dependent on the classloader. It could be during the initial load, or it could be after execution starts. Either way, the entire applet must be downloaded before execution can begin. That's just the nature of the JAR format.
Javascript files are not archived and can be executed on demand. Flash files are written out in an odd linear format that allows for streaming of the file. This allows execution to begin even before the file has completed downloading.
Re:doesn't sound too secure yet (Score:3, Informative)
You can type the brackets for <tags> by using the html codes such as < and >.
Re:doesn't sound too secure yet (Score:5, Informative)
Holy crap. AKAImBatman I usually enjoy your posts, but it's painfully clear nobody on this thread - including you - has actually read the paper.
If you had, you'd see that this system is secure. It's simple yet clever at the same time. By using a combination of x86 segmentation (which ironically you say is never used anymore!), alignment rules, static analysis and - crucially - masked jumps, it's possible to ensure that native code cannot synthesize unverified code in memory and then jump into it. If you can prevent arbitrary code synthesis, you can control what the program does. It's as simple as that.
Even though the verifier for this system is microscopic (compared to, say, a JVM), and so much more likely to be correct, NativeClient also includes a ptrace sandbox to provide an additional redundant level of protection.
I don't blame you, because until I read the paper I also believed this. Once you read it you'll slap your forehead and say, my god, it's so simple. Why didn't I think of that?
Re:doesn't sound too secure yet (Score:3, Informative)
I used to think Jazelle meant actual Java bytecode execution on the chip, until I talked to an Android developer about it. It turns out that Jazelle is quite incomplete and traps out to native code quite frequently ... for instance, to call a method.
That said, so what? You already have to write special web pages for mobile devices if you want a truly great user experience. The performance/power profiles of mobile devices are so radically differen to desktops that being unable to run x86 code natively isn't a big deal ... even if there was some kind of hardware neutral IL you still wouldn't want to use it on mobiles, for the same reason mobile browsers don't download and run WebStart applets.
Re:A remarkably bad idea. (Score:3, Informative)
Did you get past page 3? Unmasked jumps are forbidden by static analysis, so you can't create new code and jump into it. Existing code is verified against whitelisted opcode sets. Segmentation it used to prevent self-modifying code. Tricks that prevent accurate dissasembly are also forbidden by the verifier.
Re:doesn't sound too secure yet (Score:2, Informative)
Java is compiled Just-in-time, though I don't know about smaller, obscure or embedded platforms.
On mobile phones that use ARM chips Java byte-codes can also be executed directly by the CPU if the ARM chip implementes Jazelle. These ARM chips have a "J" in their names (eg. ARM926EJ-S).
Read about it here: ARM Jazelle [arm.com].
Um... what? (Score:2, Informative)
Um, a pure interpreter never "compiles" its program, in the sense of transforming the code into equivalent code in an object language. A pure interpreter usually works this way:
The easiest example to learn here would be a typical Lisp meta-circular evaulator [mit.edu].
A compiler, on the other hand, translates the AST into equivalent object code in a different language, which can then be run in an implementation of that second language (which can be either a real machine, a virtual machine, a language interpreter, ). For a pure interpreter to "compile each instruction every time it gets executed," there would have to be a program in the object language involved somewhere... and there isn't one, only an model of the successive states of a computation.