This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Fallout from dlopen() blocking SIGSYS


On Tue, Dec 03, 2019 at 03:31:34PM +0100, 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.

This entire design has a lot of things that can go wrong, and really
should be changed. Unblocking signals behind the application's (or
worse, libc/ldso's) back is a really nasty thing to do, and
intentionally breaks the "critical section" properties the blocking
very likely was intended to ensure. In a worst case, the stack pointer
might not even be valid while signals are blocked.

I don't understand the whole architecture, so it's hard for me to
offer constructive advice on how it *should* be done, but the current
way is surely wrong. The fact that it broke under a completely valid
and completely reasonable change to glibc is evidence of that; it's
silently depending on old-glibc internals. The right solution probably
involves using seccomp with a tracer process, or if the dlopen calls
are the only thing you need to filter, interposing dlopen to prevent
the nasty library from calling it. Or, just patching the nasty library
not to do nasty things you don't want it to do.

The issue was brought to my attention in relation to musl libc, and at
present it probably doesn't affect us, but it's very likely that it
could at some point in the future. Blocking signals is an idiom we use
heavily for ensuring safety of operations that might otherwise have
race conditions, making async-signal-safe locks, etc.

Rich


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]