This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Fallout from dlopen() blocking SIGSYS
- From: Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- To: Gian-Carlo Pascutto <gpascutto at mozilla dot com>, libc-alpha at sourceware dot org
- Cc: Emilio Cobos Álvarez <ealvarez at mozilla dot com>, Jed Davis <jld at mozilla dot com>, Florian Weimer <fweimer at redhat dot com>
- Date: Wed, 4 Dec 2019 17:46:54 -0300
- Subject: Re: Fallout from dlopen() blocking SIGSYS
- References: <be38a4dd-f573-6251-57e5-6c118255ce59@mozilla.com>
On 03/12/2019 11:31, Gian-Carlo Pascutto wrote:
> (reposting here per request from Florian Weimer)
>
> This glibc patch:
>
> Block signals during the initial part of dlopen
> (a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23)
>
> is going to break every Firefox release of the last few years. We use a
> seccomp-bpf filter to sandbox various processes. In some of these
> processes we don't want to do a dlopen() of untrusted code while we're
> not sandboxed yet, for example in the process we use to isolate Google's
> Widevine DRM modules from any private data on the system.
>
> seccomp-bpf will intercept various filesystem related syscalls and raise
> SIGSYS, at which moment our code will contact a broker in the parent
> process that checks if the file that's being want to read is acceptable
> to us, and then passes down the file handle.
>
> This obviously only works if the code that we load doesn't block the
> SIGSYS signal, so we interpose the signal handling functions to stop
> that from happening:
> https://searchfox.org/mozilla-central/rev/04d8e7629354bab9e6a285183e763410860c5006/security/sandbox/linux/SandboxHooks.cpp#42
>
> But, ld.so being the linker itself, this technique doesn't work for it.
> This means that it will succeed in blocking SIGSYS, try open() (or
> similar), and fail because seccomp-bpf will block it but nobody will
> handle the raised signal. Now, we hit a Linux seccomp-bpf design issue:
> SECCOMP_RET_TRAP will, if the signal is either ignored or blocked,
> unblock it and reset it to SIG_DFL (effectively).
> At this point, Firefox crashes.
>
> We are tracking the problem here:
> https://bugzilla.mozilla.org/show_bug.cgi?id=1600574
>
> This is a particularly nasty problem for us - the only
> solution/workaround so far is to disable sandboxing, and if affects old
> releases such as ESR.
>
> I'm not clear if it affects other seccomp-bpf users like Chromium - they
> use almost exactly the same way of dealing with filesystem access, but
> (all AFAIK) only for the sandboxed GPU Process which might not need to
> dlopen() things (and I'm not sure that particular sandbox is enabled on
> regular Linux to begin with).
>
> We might need to intercept the system calls that set up the signal
> handling and basically undo the above glibc change, while trying to
> ensure the conditions that caused you to make the above change don't
> hold. Or something. We're still thinking about how to cope with this.
>
Block and unblocking signals during certain parts of libc implementation
are required to avoid consistency issues and Florian can give us a better
idea why it is important on dlopen. Another implementation that glibc also
does it is posix_spawn and you might face this very issue if you use use
posix_spawn with some file action.
IMHO the issue here is seccomp-bpf is crossing some API boundaries and
adding such constraint that make harder to provide a more robust libc
implementation. The SIGSYS seemed to become a de-facto API for seccomp,
where blocking it might break some filter criteria specially if it tries
to work along with libc.
I presume glibc might try to work better with seccomp and don't add SIGSYS
on __libc_signal_block_all, however it is an incomplete solution since
SIGSYS handler can potentially make libc internal state inconsistent.
What I would expect is with current SECCOMP_RET_TRAP semantic that once
a filter is installed, the kernel would either fail or silent ignore
trying to block SIGSYS (as for SIGKILL or SIGSTOP). However it does
not help with current situation.
Would be possible to write a filter to intercept rt_sigprocmask and
exclude SIGSYS for this specific case?