Implement sandboxing on FreeBSD with Capsicum
Categories
(Core :: Security: Process Sandboxing, enhancement, P5)
Tracking
()
Tracking | Status | |
---|---|---|
firefox74 | --- | affected |
People
(Reporter: val, Unassigned)
References
Details
Attachments
(1 file)
My latest work in progress… sandboxing content with Capsicum capability mode on FreeBSD.
The idea behind Capsicum is treating file descriptors as capabilities. Once a process enters capability mode, it's in a very tight sandbox that does not have any access whatsoever to "global namespaces" — no open
, connect
, nothing like that — you can only derive new file descriptors from the ones you have: openat
(open below a directory if you have the directory opened), connectat
and other *at
calls, accept
, recvmsg
(IPC fd-passing), dup
and so on. Descriptors can have additional irreversible restrictions imposed by cap_rights_limit
, and these limits are inherited all the way (e.g. if a directory fd was limited to not having CAP_WRITE
, you won't be able to write to anything you openat
from that directory).
Most software was not written in this capability style unfortunately, so we have to LD_PRELOAD
a library that overrides libc
functions with ones that try to use pre-opened directory descriptors. One such library is https://github.com/musec/libpreopen (which has been partially reused in WASI libc!) — but it's overkill for our use in some ways (we don't impose sandboxing on unsuspecting programs so we don't need to serialize the info about opened fds to shared memory) and not enough in other ways (sysctl, fopen/opendir, symlink resolution, etc.) and it's all C and it's just better to own the code here, so I added a little mozcapsicum
library.
This is a work in progress. It mostly works already, but it only supports Wayland for now. Forkserver (bug 1607103) works, actually I've only tested with it enabled. GPU accelerated WebGL content works (tested on Mesa RadeonSI). Audio works with PulseAudio. Various other things (X11, sndio, multi-GPU, nvidia GPU?) are not tested/supported yet. Some paths are hardcoded, etc.
Requires patch from bug 1550891.
Currently dealing with a very VERY VERY weird bug: SecurityInformation
fails to deserialize in the HttpChannelChild
! Disabled assertion for now, but this is terrible. Can anyone help me debug this?
Reporter | ||
Comment 1•5 years ago
|
||
do not commit yet, see bug for info
Comment 2•5 years ago
|
||
Currently dealing with a very VERY VERY weird bug: SecurityInformation fails to deserialize in the HttpChannelChild! Disabled assertion for now, but this is terrible. Can anyone help me debug this?
Do you have more specifics on the problem you're seeing?
Reporter | ||
Comment 3•5 years ago
|
||
Oh, just had to do was to use a debug build:
[Child 77196, Main Thread] WARNING: 'NS_FAILED(rv)', file /usr/home/greg/src/hg.mozilla.org/mozilla-unified/toolkit/components/resistfingerprinting/nsRFPService.cpp, line 355
and that's getting the @mozilla.org/security/random-generator;1
service.
That's because NSS_NoDB_Init(nullptr) != SECSuccess
when initializing NSS.
And NSS needs to dlopen
by path (and in development everything is in its own dir like …/security/nss/lib/freebl/freebl_freebl3
) and to open /dev/urandom
(even though there's getentropy
/getrandom
). I have it working with some extra preloading now..
…yeah, that was also affecting WebCrypto by the way.
tested X11 (Xwayland), it does work. (glxtest failed but I'm pretty sure that's my weird setup; webgl.force-enabled showed that even WebGL works)
other things discovered by debug build:
MOZ_ASSERT_UNREACHABLE("PR_GetPhysicalMemorySize not implemented here")
in image/SurfaceCache.cpp
because it uses sysctl
and my hook for that doesn't work right now. Changing it to sysconf
(the Linux/Solaris code) which uses sysctlbyname
makes it work easily. Probably would make sense to kill the sysctl
section because I think all BSDs support sysconf
for this.
js::GetNativeStackBaseImpl()
sometimes fails MOZ_ASSERT(stackBase)
but that doesn't seem to affect anything.
Reporter | ||
Comment 4•5 years ago
|
||
huh, if PulseAudio is not running yet, Firefox tries to start it from the content process (which is not possible when sandboxed of course). Well, I guess more like libpulse
does that. Dang.
Reporter | ||
Comment 5•5 years ago
|
||
After a recent rebase, looks like it starts PulseAudio fine now, but NS_GRE_DIR
broke o_0
// in a recent commit I see that Windows is preloading nss/softokn/freebl for the network process, hmm, I should try dlopen-before-cap_enter instead of shoving more things into LD_PRELOAD
media.cubeb.backend=alsa
doesn't work here at least without env MOZ_CAPSICUM=1
. Hiding ipc/glue/GeckoChildProcessHost.cpp changes behind PR_GetEnv()
seems to help.
Updated•2 years ago
|
Comment 7•1 year ago
|
||
Val, did you abandon your work on the freebsd sandbox? Maybe you have at least some work to share?
Reporter | ||
Comment 8•1 year ago
|
||
(In reply to 6yearold from comment #7)
Val, did you abandon your work on the freebsd sandbox? Maybe you have at least some work to share?
Sort of, I've had a lot of time away from it; but I'm convinced that LD_PRELOAD trickery kinda sucks and we have to implement facilities in the OS to allow AT_FDCWD
("global" filesystem access as not-really-global) in the sandbox first. See https://reviews.freebsd.org/D38351
Comment 9•1 year ago
|
||
What do you think about "pledge" and "unveil" from OpenBSD? This should allow us to reuse OpenBSD sandbox implementation.
There is already an ongoing work on that: https://reviews.freebsd.org/D35116 and https://github.com/Math2/freebsd-pledge/
Description
•