|
|
Log in / Subscribe / Register

Security

Google's Chromium sandbox

By Jake Edge
August 19, 2009

Creating a sandbox—a safe area in which to run untrusted code—is a difficult problem. The successful sandbox implementations tend to come with completely new languages (e.g. Java) that are specifically designed to support that functionality. Trying to sandbox C code is a much more difficult task, but one that the Google Chrome web browser team has been working on.

The basic idea is to restrict the WebKit-based renderer—along with the various image and other format libraries that are linked to it—so that browser-based vulnerabilities are unable to affect the system as a whole. A successful sandbox for the browser would eliminate a whole class of problems that plague Firefox and other browsers that require frequent, critical security updates. Essentially, the browser would protect users from bugs in the rendering of maliciously-crafted web pages, so that they could not lead to system or user data compromise.

The Chrome browser, and its free software counterpart, Chromium, is designed around the idea of separate processes for each tab, both for robustness and security. A misbehaving web page can only affect the process controlling that particular tab, so it won't bring the entire browser down if it causes the process to crash. In addition, these processes are considered to be "untrusted", in that they could have been compromised by some web page exploiting a bug in the renderer. The sandbox scheme works by severely restricting the actions that untrusted processes can take directly.

At some level, Linux already has a boundary that isolates programs from the underlying system: system calls. A program that does no system calls should not be able to affect anything else, at least permanently. But it is a trivial program indeed that does not need to call on some system services. A largely unknown kernel feature, seccomp, allows processes to call a very small subset of system calls—just read(), write(), sigreturn(), and exit()—aborting a process that attempts to call any other. That is the starting point for the Chromium sandbox.

But, there are other system calls that the browser might need to make. For one thing, memory allocation might require the brk() system call. Also, the renderer needs to be able to share memory with the X server for drawing. And so on. Any additional system calls, beyond the four that seccomp allows, have to be handled differently.

A proposed change to seccomp that would allow finer-grained control over which system calls were allowed didn't get very far. In any case, that wasn't a near-term solution, so Markus Gutschke of the Chrome team went in another direction. By splitting the renderer process into trusted and untrusted threads, some system calls could be allowed for the untrusted thread by making the equivalent of a remote procedure call (RPC) to the trusted thread. The trusted thread could then verify that the system call, and its arguments, were reasonable and, if so, perform the requested action.

Chrome team member Adam Langley describes it this way:

So that's what we do: each untrusted thread has a trusted helper thread running in the same process. This certainly presents a fairly hostile environment for the trusted code to run in. For one, it can only trust its CPU registers - all memory must be assumed to be hostile. Since C code will spill to the stack when needed and may pass arguments on the stack, all the code for the trusted thread has to [be] carefully written in assembly.

The trusted thread can receive requests to make system calls from the untrusted thread over a socket pair, validate the system call number and perform them on its behalf. We can stop the untrusted thread from breaking out by only using CPU registers and by refusing to let the untrusted code manipulate the VM in unsafe ways with mmap, mprotect etc.

There are still problems with that approach, however. For one thing, the renderer code is large, with many different system calls scattered throughout. Turning each of those into an RPC is possible, but then would have to be maintained by the Chromium developers going forward. The upstream projects (WebKit, et. al.) would not be terribly interested in those changes, so each new revision from upstream would need to be patched and then checked for new system calls.

Another approach might be to use LD_PRELOAD trickery to intercept the calls in glibc. That has its own set of problems as Langley points out: "we could try and intercept at dynamic linking time, assuming that all the system calls are via glibc. Even if that were true, glibc's functions make system calls directly, so we would have to patch at the level of functions like printf rather than write."

So, a method of finding and patching the system calls at runtime was devised. It uses a disassembler on the executable code, finds each system call and turns it into an RPC to the trusted thread. Correctly parsing x86 machine code is notoriously difficult, but it doesn't have to be perfect. Because the untrusted thread runs in seccomp mode, any system call that is missed will not lead to a security breach, as the kernel will abort the thread if it attempts any but the trusted four system calls. As Langley puts it:

But we don't need a perfect disassembler so long as it works in practice for the code that we have. It turns out that a simple disassembler does the job perfectly well, with only a very few corner cases.

The last piece of the puzzle is handling time-of-check-to-time-of-use race conditions. System call arguments that are passed in memory, via pointers or for system calls with too many arguments to fit in registers, can be changed by the, presumably subverted, untrusted thread between the time they are checked for validity and when they are used. To handle that, a trusted process, which is shared between all of the renderers, is created to check system calls that cannot be verified within the address space of the untrusted renderer.

The trusted process shares a few pages of memory with each trusted thread, which are read-only to the trusted thread, and read-write for the trusted process. System calls that cannot be handled by the trusted thread, either because some of the arguments live in memory, or because the verification process is too complex to be reasonably done in assembly code, are handed off to the trusted process. The arguments are copied by the trusted process into its address space, so they are immune to changes from the untrusted code.

While the current implementation is for x86 and x86-64—though there are still a few issues to be worked out with the V8 Javascript engine on x86-64—there is a clear path for other architectures. Adapting or writing a disassembler and writing the assembly language trusted thread are the two pieces needed to support each additional architecture. According to Langley:

The former is probably easier on many other architectures because they are likely to be more RISC like. The latter takes some work, but it's a coding problem only at this point.

There are some potential pitfalls in this sandbox mechanism. Bugs in the implementation of the trusted pieces—either coding errors or mistakes made in determining which system calls and arguments are "safe"—could certainly lead to problems. Currently, deciding which calls to allow is done on an ad hoc basis, by running the renderer, seeing which calls it makes, and deciding which are reasonable. The outcome of those decisions are then codified in syscall_table.c.

One additional, important area that is not covered by the sandbox are plugins like Flash. Restricting what plugins can do does not fit well with what users expect, which makes plugins a major vector for attack. Langley said that the plugin support on Linux is relatively new, but "our experience on Windows is that, in order for Flash to do all the things that various sites expect it to be able to do, the sandbox has to be so full of holes that it's rather useless". He is currently looking at SELinux as a way to potentially restrict plugins, but, for now, they are wide open.

This is a rather—some would say overly—complex scheme. It is still in the experimental stage, so changes are likely, but it does show one way to protect browser users from bugs in the HTML renderer that might lead to system or data compromise. It certainly doesn't solve all of the web's security problems, but could, over time, largely eliminate a whole class of attacks. It is definitely a project worth keeping an eye on.

[ Many thanks to Adam Langley, whose document was used as a basis for this article, and who patiently answered questions from the author. ]

Comments (31 posted)

Brief items

Another kernel NULL pointer vulnerability

Tavis Ormandy has disclosed a new, easily-exploited NULL pointer vulnerability in the Linux kernel; this one comes from the networking code when any of a number of relatively obscure protocols are used. A fix has been merged into the mainline, but there's likely to be a lot of exploitable kernels out there.

Full Story (comments: 13)

New vulnerabilities

cdf: buffer overflows

Package(s):cdf CVE #(s):CVE-2009-2850
Created:August 19, 2009 Updated:August 19, 2009
Description: Versions of the cdf (common data format) library prior to 3.3.0 suffer from a number of heap-based buffer overflows which could be exploited (by a malicious CDF file) to execute arbitrary code.
Alerts:
Gentoo 200908-06 cdf 2009-08-18

Comments (none posted)

Compress::Raw::Bzip2: buffer overflow

Package(s):Compress::Raw::Bzip2 CVE #(s):CVE-2009-1884
Created:August 19, 2009 Updated:August 24, 2009
Description: The Perl Compress::Raw::Bzip2 library (prior to version 2.020) suffers from a buffer overflow which could possibly be exploited to execute arbitrary code.
Alerts:
Fedora FEDORA-2009-8868 perl-Compress-Raw-Bzip2 2009-08-22
Fedora FEDORA-2009-8888 perl-Compress-Raw-Bzip2 2009-08-22
Mandriva MDVSA-2009:207 perl-Compress-Raw-Bzip2 2009-08-19
Gentoo 200908-07 Compress::Raw 2009-08-18

Comments (none posted)

curl: null prefix vulnerability

Package(s):curl wget CVE #(s):CVE-2009-2417 CVE-2009-2408
Created:August 14, 2009 Updated:June 24, 2011
Description: From the Red Hat alert: Scott Cantor reported that cURL is affected by the previously published "null prefix attack", caused by incorrect handling of NULL characters in X.509 certificates. If an attacker is able to get a carefully-crafted certificate signed by a trusted Certificate Authority, the attacker could use the certificate during a man-in-the-middle attack and potentially confuse cURL into accepting it by mistake.

The wget tool also suffers from the same vulnerability.

Alerts:
Gentoo 201301-01 firefox 2013-01-07
Ubuntu USN-1158-1 curl 2011-06-24
Mandriva MDVSA-2009:330 kdelibs 2009-12-10
Mandriva MDVSA-2009:206-1 wget 2009-12-04
Mandriva MDVSA-2009:203-1 curl 2009-12-04
Mandriva MDVSA-2009:217-1 mozilla-thunderbird 2009-08-23
Gentoo 200909-20 curl 2009-09-25
Mandriva MDVSA-2009:217-2 mozilla-thunderbird 2009-10-08
Mandriva MDVSA-2009:197-2 nss 2009-09-11
CentOS CESA-2009:1432 seamonkey 2009-09-10
Red Hat RHSA-2009:1432-01 seamonkey 2009-09-09
SuSE SUSE-SR:2009:014 dnsmasq, icu, libcurl3/libcurl2/curl/compat-curl2, Xerces-c/xerces-j2, tiff/libtiff, acroread_ja, xpdf, xemacs, mysql, squirrelmail, OpenEXR, wireshark 2009-09-01
Debian DSA-1874-1 nss 2009-08-26
rPath rPSA-2009-0124-1 curl 2009-08-24
Mandriva MDVSA-2009:217 mozilla-thunderbird 2009-08-23
Mandriva MDVSA-2009:216 mozilla-thunderbird 2009-08-23
Debian DSA-1869-1 curl 2009-08-19
Mandriva MDVSA-2009:206 wget 2009-08-18
Slackware SSA:2009-226-01 curl 2009-08-17
Mandriva MDVSA-2009:203 curl 2009-08-15
Ubuntu USN-818-1 curl 2009-08-17
CentOS CESA-2009:1209 curl 2009-08-14
Red Hat RHSA-2009:1209-01 curl 2009-08-13
SuSE SUSE-SA:2009:048 MozillaFirefox 2009-10-20
SuSE SUSE-SR:2009:016 silc-toolkit, open-iscsi, strongswan,freeswan,openswan, mutt, openldap2, cyrus-imapd, java-1_6_0-openjdk, postgresql, IBMJava2-JRE/java-1_4_2-ibm, wireshark, freeradius, dovecot 2009-10-13

Comments (none posted)

dillo: integer overflow

Package(s):dillo CVE #(s):CVE-2009-2294
Created:August 19, 2009 Updated:August 19, 2009
Description: Dillo's PNG-handling code contains an integer overflow vulnerability; version 2.1.1 has the fix.
Alerts:
Gentoo 200908-10 dillo 2009-08-18

Comments (none posted)

dokuwiki: input sanitization error

Package(s):dokuwiki CVE #(s):CVE-2009-1960
Created:August 19, 2009 Updated:August 19, 2009
Description: Dokuwiki (prior to version 2009-02-14b) suffers from an input sanitization error which could enable information disclosure or code execution exploits.
Alerts:
Gentoo 200908-09 dokuwiki 2009-08-18

Comments (none posted)

kernel: privilege escalation

Package(s):kernel CVE #(s):CVE-2009-2692
Created:August 18, 2009 Updated:October 5, 2009
Description: From the Mandriva advisory: The Linux kernel 2.6.0 through 2.6.30.4, and 2.4.4 through 2.4.37.4, does not initialize all function pointers for socket operations in proto_ops structures, which allows local users to trigger a NULL pointer dereference and gain privileges by using mmap to map page zero, placing arbitrary code on this page, and then invoking an unavailable operation, as demonstrated by the sendpage operation on a PF_PPPOX socket.
Alerts:
Red Hat RHSA-2009:1469-01 kernel 2009-09-30
Red Hat RHSA-2009:1457-01 kernel 2009-09-22
SuSE SUSE-SR:2009:015 OpenOffice_org, OpenOffice_org-math, dnsmasq, gnutls, ia32el, ib-bonding-kmp-rt/kernel-rt, libxml, opera, perl-IO-Socket-SSL, xen 2009-09-15
Mandriva MDVSA-2009:233 kernel 2009-09-14
Red Hat RHSA-2009:1239-02 kernel-rt 2009-09-01
Red Hat RHSA-2009:1239-01 kernel-rt 2009-09-01
CentOS CESA-2009:1233 kernel 2009-08-29
Red Hat RHSA-2009:1233-01 kernel 2009-08-27
Fedora FEDORA-2009-9044 kernel 2009-08-27
Slackware SSA:2009-231-01 linux 2009-08-20
CentOS CESA-2009:1222 kernel 2009-08-24
CentOS CESA-2009:1223 kernel 2009-08-24
Red Hat RHSA-2009:1222-02 kernel 2009-08-24
Red Hat RHSA-2009:1223-02 kernel 2009-08-24
SuSE SUSE-SA:2009:045 kernel 2009-08-20
Ubuntu USN-819-1 linux, linux-source-2.6.15 2009-08-19
Slackware SSA:2009-230-01 kernel 2009-08-19
rPath rPSA-2009-0121-1 kernel 2009-08-18
Fedora FEDORA-2009-8649 kernel 2009-08-15
Fedora FEDORA-2009-8647 kernel 2009-08-15
Debian DSA-1865-1 linux-2.6 2009-08-16
Debian DSA-1864-1 linux-2.6.24 2009-08-16
Debian DSA-1862-1 linux-2.6 2009-08-14
Mandriva MDVSA-2009:205 kernel 2009-09-17
Fedora FEDORA-2009-10165 kernel 2009-10-03

Comments (none posted)

pidgin: remote code execution

Package(s):pidgin CVE #(s):CVE-2009-2694
Created:August 19, 2009 Updated:December 7, 2009
Description: A flaw in the Pidgin MSN protocol handler can enable the execution of arbitrary code from a malicious MSN message.
Alerts:
Mandriva MDVSA-2009:321 pidgin 2009-12-06
Mandriva MDVSA-2009:230 pidgin 2009-09-11
Fedora FEDORA-2009-8804 libnice 2009-08-20
Fedora FEDORA-2009-8804 gupnp-igd 2009-08-20
Fedora FEDORA-2009-8804 farsight2 2009-08-20
Fedora FEDORA-2009-8804 pidgin 2009-08-20
Fedora FEDORA-2009-8791 pidgin 2009-08-20
Ubuntu USN-820-1 pidgin 2009-08-20
Slackware SSA:2009-231-02 pidgin 2009-08-20
Debian DSA-1870-1 pidgin 2009-08-19
CentOS CESA-2009:1218 pidgin 2009-08-18
CentOS CESA-2009:1218 pidgin 2009-08-19
Red Hat RHSA-2009:1218-01 pidgin 2009-08-18
Gentoo 200910-02 pidgin 2009-10-22

Comments (none posted)

thunderbird: multiple vulnerabilities

Package(s):thunderbird CVE #(s):
Created:August 19, 2009 Updated:August 21, 2009
Description:

From the Fedora advisory:

Update to upstream version 3.0 Beta3. It includes security fixes recently fixed in stable Thunderbird 2.x and Firefox/Gecko security fixes:
http://www.mozilla.org/security/known-vulnerabilities/thunderbird20.html
http://www.mozilla.org/security/known-vulnerabilities/firefox30.html

Alerts:
Slackware SSA:2009-232-01 mozilla-thunderbird 2009-08-21
Ubuntu USN-817-1 thunderbird 2009-08-20
Fedora FEDORA-2009-8535 thunderbird 2009-08-15

Comments (none posted)

viewvc: multiple vulnerabilities

Package(s):viewvc CVE #(s):
Created:August 13, 2009 Updated:August 19, 2009
Description: viewvc has multiple vulnerabilities. From the Fedora alert: - security fix: validate the 'view' parameter to avoid XSS attack - security fix: avoid printing illegal parameter names and values
Alerts:
Fedora FEDORA-2009-8507 viewvc 2009-08-12
Fedora FEDORA-2009-8501 viewvc 2009-08-12

Comments (none posted)

zope: multiple vulnerabilities

Package(s):zope2.10/zope2.9 CVE #(s):CVE-2009-0668 CVE-2009-0669
Created:August 19, 2009 Updated:May 11, 2011
Description:

From the Debian advisory:

Due to a programming error an authorization method in the StorageServer component of ZEO was not used as an internal method. This allows a malicious client to bypass authentication when connecting to a ZEO server by simply calling this authorization method (CVE-2009-0668).

The ZEO server doesn't restrict the callables when unpickling data received from a malicious client which can be used by an attacker to execute arbitrary python code on the server by sending certain exception pickles. This also allows an attacker to import any importable module as ZEO is importing the module containing a callable specified in a pickle to test for a certain flag (CVE-2009-0668).

The update also limits the number of new object ids a client can request to 100 as it would be possible to consume huge amounts of resources by requesting a big batch of new object ids. No CVE id has been assigned to this.

Alerts:
Debian DSA-2234-1 zodb 2011-05-10
SuSE SUSE-SR:2009:020 apache2-mod_jk, cacti, cups, expat, finch/pidgin, htmldoc, kdelibs3/kdelibs4, libpoppler/poppler, lighttpd, opera, perl-HTML-Parser, pyxml, seamonkey, wireshark/ethereal, xntp, zope/zope3 2010-01-12
Debian DSA-1863-1 zope2.10/zope2.9 2009-08-15
Ubuntu USN-848-1 zope3 2009-10-14

Comments (none posted)

Page editor: Jake Edge
Next page: Kernel development>>


Copyright © 2009, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds