Closed Bug 742434 (desktop-seccomp) Opened 12 years ago Closed 8 years ago

Enable seccomp-bpf for nightly desktop Firefox content processes on Linux

Categories

(Core :: Security: Process Sandboxing, enhancement)

All
Linux
enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla50
Tracking Status
firefox50 --- fixed

People

(Reporter: Thomas.Ludwig, Assigned: tedd)

References

(Blocks 2 open bugs)

Details

(Whiteboard: sblc1)

Attachments

(3 files)

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0
Build ID: 20120329123613

Steps to reproduce:

https://bugzilla.mozilla.org/show_bug.cgi?id=730956 discusses sandboxing Firefox in general. https://bugzilla.mozilla.org/show_bug.cgi?id=387248 suggests using the Mac OS X sandbox. 

But also for Linux sandbox solutions are available. They are used in Google Chrome/Chromium and are described on https://code.google.com/p/chromium/wiki/LinuxSandboxing which points to further references. Note that the seccomp sandbox is not enabled by default in Chrome - you have to start the browser by adding --enable-seccomp-sandbox as a start parameter. Then chrome://sandbox/ shows the SUID sandbox and the seccomp sandbox as enabled. An additional document for seccomp is http://outflux.net/teach-seccomp/

One might argue that Linux provides other security modules like SELinux, AppArmor or Tomoyo. However, SELinux is only available on some (Redhat-based) distributions, and the AppArmor profile for Firefox in Ubuntu is not enabled by default and often requires additional rules which is too much for most users. Contrary to this, a SUID and/or seccomp sandbox works "out of the box". Thus, *every* Linux user would benefit. Besides, it would help to refute the alleged superiority of Chrome security-wise.
OS: Windows 7 → Linux
Hardware: x86 → All
Severity: normal → enhancement
This is also relevant to B2G.
Please add this bug to https://wiki.mozilla.org/Features/Security/Low_rights_Firefox just to make sure that Linux is not forgotten ;-)
See also https://github.com/redpig/linux
Linux is definitely not forgotten ! :)

See bug 746280, which is the tracking bug for 'low rights' content processes in b2g - Guillaume's plan is to use seccomp there, i believe - we are very hopeful the work for b2g can filter back to the desktop. 

I will add this bug to the feature page, thanks !
Status: UNCONFIRMED → NEW
Ever confirmed: true
Blocks: 730956
Useful link regarding seccomp filters:
http://outflux.net/teach-seccomp/
Note that, https://wiki.mozilla.org/B2G/Architecture/Runtime is a more general documentation about the seccomp (filter) possible implementation into Gecko for B2G, although I don't know how much of it can be used/ported to desktop Firefox since it requires multiprocess support (as per bug 746280)
Component: Untriaged → Security
Depends on: b2g-seccomp
Summary: Consider using a Linux sandbox for improved security → Use seccomp to sandbox desktop Firefox on Linux
Summary: Use seccomp to sandbox desktop Firefox on Linux → Use seccomp-bpf to sandbox desktop Firefox on Linux
Ian changed the summary of this bug by focusing it to seccomp-bpf. While seccomp-bpf is extremely important, the setuid sandbox - as explained on https://code.google.com/p/chromium/wiki/LinuxSandboxing - should not neglected. 

In my understanding, the setuid sandbox chroots a process thus restricting access to most resources. It also creates a new network and PID namespace. More details on http://www.cr0.org/paper/jt-ce-sid_linux.pdf. Seccomp-bpf, on the other hand, filters system calls thus protecting the kernel.

Both sandboxes complement each other. That's why both should be implemented in Firefox.
seccomp-bpf does not "protect the kernel" per se:

any kind of process communication is gated by systems calls (even a netlink call requires a system call first). by denying systems calls, it _may_ protect the kernel as a side effect but its not it's primary goal.

when calls such as accept, open, etc are denied, having a chroot-style sandbox or a network namespace isn't reducing the attack surface, as the calls are before the chroot/namespacing code.

these can be useful if the calls are allowed and unfiltered, however.

The seccomp sandbox for desktop AFAIK follow +- the B2G sandbox which aims to have those calls entierely denied. I would think desktop would want to go in the same direction (?)

Note that when seccomp-bpf is not available other types of sandbox can/should still be used, even the rlimit() style sandbox reduces the attack surface quite a bit if seccomp-bpf is not available. For example, OpenSSH has 3 such sandboxes (chroot, rlimit, seccomp-bpf) on Linux and fallsback accordingly.
seccomp-bpf may not protect the kernel per se but by filtering system calls "it provides a clearly defined mechanism for minimizing the exposed kernel surface." (https://lwn.net/Articles/475049/)

A combination of a setuid and seccomp-bpf sandbox obviously has some advantages according to this blog post by a Google Chrome developer (http://blog.cr0.org/2012/09/introducing-chromes-next-generation.html): "The setuid sandbox gives a few easy to understand semantic properties: no file system access, no process access outside of the sandbox, no network access. It makes it much easier to layer a seccomp-bpf sandbox on top."
As stated by comment 11, it _may_ protect the kernel as a side effect. That is, since communicating with the kernel always starts with a system call, if you don't have that call, you can't exploit a bug beneath it. But its not _made_ to protect the kernel.

The point i'm trying to make is that if you can't make the systems calls related to file system access, there is _no_ filesystem access, regardless of chrooting or namespacing.

If you do need _some_ filesystem access, then yes, chrooting can be used (or selinux for example, which chrome also supports as a sandbox "model").
In our case I believe the security monitor process (the parent process) both in B2G and Desktop provides the file access control, and being a different process than, and a parent of the sandboxed process, is not affected by seccomp-bpf denying _all_ and _any_ file system access.

It may still be interesting to sandbox the parent process itself with such a sandbox, however.

I'm basically restating comment 11, hopefully with clearer statements :)
Thomas, 

you make good points about the setuid sandbox - thank you. Our sandboxing work is mostly focused on Firefox OS right now, where we essentially have a setuid sandbox for apps (each app runs as its own uid, like Android) and decent process separation already. That's why I changed this bug to focus on seccomp-bpf, it's essentially now about making sure that work lands and is usable for desktop. I hadn't really considered doing a setuid sandbox for desktop since we've been focused on Firefox OS, but it's definitely on the table (and something we should discuss). Guillaume's points about not needing a setuid sandbox if seccomp-bpf doesn't allow "open" syscalls anyways are well taken, but I think a setuid sandbox might be an easier/faster path to get some protection sooner. I also strongly agree with Julien's comment from his blog you pasted that the setuid sandbox provides a very easy to understand model to layer on top of.
Alias: desktop-seccomp
Summary: Use seccomp-bpf to sandbox desktop Firefox on Linux → Use seccomp-bpf to sandbox desktop Firefox content processes on Linux
Assignee: nobody → jld
No longer depends on: b2g-seccomp
See Also: → b2g-seccomp
(In reply to Jed Davis [:jld] from comment #15)
> This bug

Ahem.

This bug will cover getting seccomp-bpf applied to desktop content processes, even though the policy won't be an effective sandbox without followup work, so that unexpected breakage turns up sooner rather than later.

There are already separate bugs for removing filesystem/network access, and for reducing the set of allowed system calls more generally, so I think it makes sense to let those continue to be what they were filed as, and adjust bug dependencies as needed to reflect that they're also necessary to have a “sandbox”.
Component: Security → Security: Process Sandboxing
Product: Firefox → Core
Summary: Use seccomp-bpf to sandbox desktop Firefox content processes on Linux → Apply seccomp-bpf to desktop Firefox content processes on Linux
Version: 12 Branch → unspecified
Is the sandbox actually disabled by default on Linux? If so, is there any work going on to enable it ?
(In reply to AnAkkk from comment #17)
> Is the sandbox actually disabled by default on Linux? If so, is there any
> work going on to enable it ?

Short answer: yes, and yes, but it's going to be a lot of work.

Very long answer: It's disabled because it doesn't work yet.  It's not really a meaningful sandbox if it's trivial to run arbitrary code by writing to a file like ~/.bashrc or connecting to a local-domain socket service that implements same-domain security or something like that, and the current seccomp-bpf policy allows a lot of direct filesystem and network access.  It's also, currently, not permissive enough to avoid breaking things (audio, at least), and there's always the risk of breaking things when system libraries change.  It's hard to justify breaking functionality for “sandboxing” that doesn't provide a meaningful increase in security.

The biggest problem here is probably PulseAudio, because it does a lot of things that are difficult to sandbox (connect to arbitrary sockets, change file permissions, test whether other clients using the same shared memory are still running, maybe more that I'm forgetting or haven't discovered yet).  I'd been hoping that we'd move audio device access into the parent process soon, but no other OS needs it (Windows doesn't unless it's at a sandbox level where GPU drivers also don't work, and getting GPU access out of the content process is *very* difficult, I'm told), and making it work while keeping latency acceptable is not easy.  That's bug 1104619.

There are also file:/// URLs, both directly navigated to (bug 922481) and used indirectly via chrome:// and resource:// (including via add-ons; bug 1136836 and bug 1109293).  Those are difficult to deal with; even on OS X, which has the best tools for this, the sandboxed content process can read from any file except a small blacklist that I think is just intended to protect other browser profiles.  Trying to determine the set of file:/// URLs accessed by user intent is difficult; see, e.g., http://joevennix.com/2015/06/24/Adventures-in-Browser-Exploitation-Part-II--Safari-8-UXSS.html .   The best bet there might be if something like bug 1170894 can be used to keep file:/// in a separate content process from remote content.

And there's X11, which the content process uses directly for GPU access as well as 2D rendering, and whose security model is that any client can do anything to any resource.  See bug 1129492.  That one is at least a little more complicated to exploit, but it seems hard to deal with short of having an application-level proxy for the X11 protocol.  Or using Wayland instead.

But the next step is bug 930258, the one about brokering filesystem access to be able to filter on path names, which I'm working on now — initially for B2G, but the idea is to use the same code on desktop, where we can't really have a meaningful sandbox without something like that.
Thanks for the detailed reply :)
Keywords: meta
Assignee: jld → nobody
As a first step to enable content process sandboxing on Linux we should enable in nightly first.

Since this bug has already set the right dependencies for this effort, it makes sense to use this bug instead of filing a separate one.
Keywords: meta
Summary: Apply seccomp-bpf to desktop Firefox content processes on Linux → Enable seccomp-bpf for nightly desktop Firefox content processes on Linux
Whiteboard: sblc1
Depends on: 1259273
Depends on: 1273852, 1273859
Depends on: 1274873
Depends on: 1275781
Depends on: 1275785
Depends on: 1275786
Depends on: 1275920
Depends on: 1276470
After performing all kinds of testing during the last couple of weeks/month, I think we are getting to a point where we can enable seccomp on nightly to see if the current whitelist crashes Firefox or not.

Try push for build (only patches of this bug): https://treeherder.mozilla.org/#/jobs?repo=try&revision=9a8b9996e4f6

Try push running all our Linux tests: https://treeherder.mozilla.org/#/jobs?repo=try&revision=f9c0b80ca328

mda and b-m are failing, but those don't seem to be related to the sandbox. Also the above try push includes the patches this bug depends on but haven't landed yet.

The first patch introduces a pref that allows users to disable seccomp without having to recompile the code, which makes Firefox usable while we are fixing the problems the user experience.

> security.sandbox.content.level 

in about:config can be used to enable (value > 0) or disable (value 0) the sandbox.

Our tests may not cover all use cases, that's why we first enable it for nightly only and see how it goes.

Also note, the current state of the sandbox is very permissive, reducing the whitelist is the next step once the current state is running stable for our users.
Assignee: nobody → julian.r.hector
Blocks: 1280415
I created Bug 1280415 to track issues encountered on nightly. Please block Bug 1280415 when filing a new bug.
Attachment #8763053 - Flags: review?(jld) → review+
Attachment #8763055 - Flags: review?(jld) → review+
Failing on inbound: https://treeherder.mozilla.org/#/jobs?repo=mozilla-inbound&revision=4e0e2373e234a603edd01f9c15db27c5972de79c

/home/worker/workspace/build/src/security/sandbox/linux/SandboxFilter.cpp:407:3: error: bad implicit conversion constructor for 'ContentSandboxPolicy'
(In reply to Julian Hector [:tedd] [:jhector] from comment #24)

> Try push for build (only patches of this bug):
> https://treeherder.mozilla.org/#/jobs?repo=try&revision=9a8b9996e4f6
> ...
> mda and b-m are failing, but those don't seem to be related to the sandbox.

The "S" failure very much is though!
Thanks :gcp, this patch adds the 'explicit' keyword to the constructor.

All green now on try builds:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=4321e4481833
Attachment #8767868 - Flags: review?(gpascutto)
Attachment #8767868 - Flags: review?(gpascutto) → review+
backed out for test failurs like https://treeherder.mozilla.org/logviewer.html#?job_id=31192684&repo=mozilla-inbound
Flags: needinfo?(julian.r.hector)
(In reply to Julian Hector [:tedd] [:jhector] from comment #24)
> mda and b-m are failing, but those don't seem to be related to the sandbox.

Are You Sure?

INFO - 2103 INFO ICE Server: Dropping packet from 10.134.157.249:40399, no permission on allocation IPv4Address(UDP, '10.134.157.249', 36498)
Backout by cbook@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/517b75503fcc
Backed out changeset 7a504a73b6f2 
https://hg.mozilla.org/integration/mozilla-inbound/rev/23f49057b4aa
Backed out changeset 730fcdccb26e 
https://hg.mozilla.org/integration/mozilla-inbound/rev/c71004cf2ebf
Backed out changeset 3601419d2e4b for test failures like  /content-security-policy/media-src/media-src-7_3.html timeouts
:tomcat, sorry about the trouble.

:gcp I am pretty sure, I ran couple of try runs with basically the same patches applied for example this one: https://treeherder.mozilla.org/#/jobs?repo=try&revision=439b0d007eff&selectedJob=22640199

but that was a while back, things change, I will run a full try run with latest mc and these patches applied.
Flags: needinfo?(julian.r.hector)
This is your earlier try push:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=f9c0b80ca328

It was red, even with re-triggers, on exactly the same test the inbound push went red. Doesn't seem to have been the same test at a first look, but then again, looking at the log:

03:21:13     INFO -  Sandbox: seccomp sandbox violation: pid 2150, syscall 355, args 2638475927 0 0 0 2990520976 3076939140.  Killing process.

That's getrandom().
FWIW that comes from this log. I'm not sure if the log Tomcat indicates is our fault, but this one clearly is:
https://treeherder.mozilla.org/logviewer.html#?job_id=31195021&repo=mozilla-inbound#L1878

I'm guessing the buildbots have a slightly different libc/glib etc that are using that call, as clearly the ones on our local systems don't. We can just whitelist this one.
Depends on: 1284452
Depends on: 1284912
Depends on: 1285507
No longer depends on: 1285507
Depends on: 1285606
No longer depends on: 1285606
Depends on: 1294331
Depends on: 1329216
You need to log in before you can comment on or make changes to this bug.